Partial Template Specialization Based on "Signed-Ness" of Integer Type

Partial template specialization based on signed-ness of integer type?

You can use enable_if with the is_unsigned type trait:

template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, bool>::type f(T n)
{
return n <= 100;
}

template <typename T>
typename std::enable_if<!std::is_unsigned<T>::value, bool>::type f(T n)
{
return n >= 0 && n <= 100;
}

You can find enable_if and is_unsigned in the std or std::tr1 namespaces if your compiler supports C++0x or TR1, respectively. Otherwise, Boost has an implementation of the type traits library, Boost.TypeTraits. The boost implementation of enable_if is a little different; boost::enable_if_c is similar to the TR1 and C++0x enable_if.

Extract signed-ness of template type?

Pre-C++11 you can use this implementation of std::conditional:

template<bool B, class T, class F>
struct conditional { typedef T type; };
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

Then we can write a struct to extract the signedness of a type:

template <typename T>
struct signedness {
typedef typename conditional<T(-1)<T(0),int,unsigned>::type type;
};

Then just declare base as being that type:

std::string IntToString(T a, 
typename signedness<T>::type base = 10){

Get the signed/unsigned variant of an integer template parameter without explicit traits

The answer is in <type_traits>

For determining the signed-ness of a type use std::is_signed and std::is_unsigned.

For adding/removing signed-ness, there is std::make_signed and std::make_unsigned.

signed/unsigned trait programming

In this case, there's a few ways to go about it, but my favorite for cases where there's a limited number of variants (e.g., a boolean or two saying which way it should behave), partial specialization of a template is usually the best way to go:

// Original implementation with default boolean for the variation type
template <typename T, bool is_unsigned = std::is_unsigned<T>::value>
class FXP {
// default implementation here
};

Your next step is to then provide a partial specialization that takes the typename T, but only works for a specific variant of the template parameters (e.g. true or false).

template <typename T>
class FXP<T, false> {
// partial specialization when is_unsigned becomes false
};

template <typename T>
class FXP<T, true> {
// partial specialization when is_unsigned becomes true
};

In this case, if you write a default implementation, you only need to make a specialization for the case that's non-default (like the true case).

Here's an example, where the default case gets overridden by a specialized template parameter:
http://coliru.stacked-crooked.com/a/bc761b7b44b0d452

Note that this is better only for smaller cases. If you need complex tests, you're better off using std::enable_if and some more complicated template parameters (like in DyP's answer).

Good luck!

Get rid of warning in templated method due to unsignedness

With Tag dispatching and traits:

template <typename T>
bool is_negative(T t, std::true_type)
{
return t < 0;
}
template <typename T>
bool is_negative(T t, std::false_type)
{
return false;
}

template<class IntegralType>
void randomFunction(IntegralType t)
{
...
if (is_negative(t, std::is_signed<IntegralType>::type())
...
}

std::is_signed can be implemented in C++03.

can template alias be used for partial specialization?

The code is perfectly fine in C++11. The Clang's warning can be ignored.

Adding more types to template specialization

From the std::array C++ documentation:

template< 
class T,
std::size_t N
> struct array;

So, you need

template<std::size_t I> struct meta<std::array<double, I>> {
static constexpr const char* class_name = "double[]";
static const char* get_name() { return class_name; }
};

Because int and std::size_t are two different types (having different signed-ness), the partial template specialization won't match. Changing int to size_t works.


In summary: Read the documentation.



Related Topics



Leave a reply



Submit