Check for integral type

1.5k views Asked by At

How can I check if a template parameter type is integral?

I know that I can use std::is_integral<> in C++11 to do this. There's even a question here for that.

How to check that template's parameter type is integral?

I also know that Boost provides this feature. I'm interested in how to "manually" make this check.

There's no specific problem I'm trying to solve. This is an abstract question about C++.

3

There are 3 answers

3
Rapptz On BEST ANSWER

Manually speaking you have to first define a template class that defines whether something is true of false at compile time:

template<bool B>
struct bool_type {
    static const bool value = B;
};

typedef bool_type<true> true_type;
typedef bool_type<false> false_type;

After that you start defining the trait class with the default cases and some redirecting cases:

template<typename T>
struct is_integral : false_type {};

template<typename T>
struct is_integral<const T> : is_integral<T> {};

template<typename T>
struct is_integral<volatile T> : is_integral<T> {};

Then the core of it will come through manually instantiating the template specialisation for integral types.

template<>
struct is_integral<int> : true_type {};

template<>
struct is_integral<long> : true_type {};

// etc

That's one way to do it anyway. You could have a macro that would automatically generate these to make it easier. However the basic idea remains the same, they just check if a specific type is part of the group you're asking for and it's done through some sort of look-up. This way (explicit template instantiation) is probably the easiest way to do it.

0
Christopher Oicles On

You can do something like this to determine whether a numeric type is integral or can have a fractional part. This code will not compile with non-numeric types, but further metaprogramming could be added for filtering arbitrary types if that's what you want. This could also be modified to provide a "true" type or "false" type (like Rapptz' answer) instead of a static bool value.

I gave two ways to test a value (rather than a type). One uses decltype to get the type and the other uses a template function. The function can be used if decltype is not available, but its result probably can only be used at run-time (constexpr is probably not available if decltype isn't).

And to make sure it is clear: the VALUE_IS_INTEGER macro and value_is_integer template function do not test whether or not the given value is a whole number, they test whether or not a value's type is integral.

#include <iostream>

template <typename T, bool IS_INTEGRAL = T(3)/T(2)<=T(1) || T(3)/T(2)>=T(2)>
   struct IsIntegerTypeCheck {
   static const bool is_integer = IS_INTEGRAL;
};

#define TYPE_IS_INTEGER(type)   (IsIntegerTypeCheck<type>::is_integer)
#define VALUE_IS_INTEGER(value) (IsIntegerTypeCheck<decltype(value)>::is_integer)

template <typename T> static bool value_is_integer(const T& value) {
    return IsIntegerTypeCheck<T>::is_integer; 
}

template <typename ST>
void dump_bool(ST message, bool value) {
    std::cout << message << ' ' << (value ? "true" : "false") << "\n";
}

int main() {
    static const bool   int_is_integer = TYPE_IS_INTEGER(int);
    static const bool   float_is_integer = TYPE_IS_INTEGER(float);
    static const long   unity = 1;
    static const double tau = 3.1415925 * 2;
    static const bool   unity_is_integer = VALUE_IS_INTEGER(unity);
    static const bool   tau_is_integer = value_is_integer(tau);
    dump_bool("int is integer:  ", int_is_integer);
    dump_bool("float is integer:", float_is_integer);
    dump_bool("unity is integer:", unity_is_integer);
    dump_bool("tau is integer:  ", tau_is_integer);
    return 0;
}
0
P0W On

This might be "link only" answer but IMHO it answers the question,

Possible Implementation :

Line 151 to 256 From GCC 4.8.1 Online Docs

See other typedefs as well coded above Line 151 .