Is there an easy way to check the fundamental type
You can use a specialized specialization to get what you want.
// General template
template<typename T>
struct IsFundamentalType { enum { result = false }; };
// Template specializations for each fundamental type
template<>
struct IsFundamentalType<char> { enum { result = true }; };
template<>
struct IsFundamentalType<int> { enum { result = true }; };
template<>
struct IsFundamentalType<short> { enum { result = true }; };
template<>
struct IsFundamentalType<float> { enum { result = true }; };
// And so on for other fundamental types ...
class NonFundamentalType
{
};
template<typename T>
void DoSomething(const T& var)
{
if(IsFundamentalType<T>::result)
{
printf("I'm fundamental type!\n");
}
else
{
printf("I'm not a fundamental type!\n");
}
}
int main()
{
int i = 42;
char c = 42;
short s = 42;
float f = 42.0f;
NonFundamentalType nft;
DoSomething(i);
DoSomething(c);
DoSomething(s);
DoSomething(f);
DoSomething(nft);
}
In this code, if you pass a type type int
or char
, the compiler will use a specialization IsFundamentalType
(given that you have defined specializations for all major types). Otherwise, the compiler will use the generic template, as is the case for a class NonFundamentalType
. The important thing is that the specialized ones have a member result
defined as true
, and the general template also has an element result
defined as false
. Then you can use the member result
for the operator if
. Compiler optimizations should be able to elude the operator if
by seeing that the expression boils down to a constant true / false, so doing something like this shouldn't impose an execution penalty.
a source to share
don't reinvent wheel boost :: type_traits
http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/index.html
a source to share
The easiest way is to create an object of type. Basically, you create an object (let's call it is_fundamental <T>) that is type parameterized and inherits from boost :: type_traits :: no_type by default; then you specialize the object to all major types, making that specialization inherit from boost :: type_traits :: yes_type. So, you can use is_fundamental <T> :: value as a boolean value that will tell you if type T is or not a fundamental type. Most of the time, you don't really need to know if a type is fundamental or not, and when you do, it almost always includes templates, so it can do that as well.
I should also point out that Boost already defines boost :: type_traits :: is_fundamental , which does what you want. You can see in is_fundamental.hpp that they define it in terms of other objects of type objects; a type is fundamental if it is a built-in arithmetic type or is "void" (which is also considered fundamental). Trying to get into the details from Boost can be a little confusing, but oversimplification:
template<typename T, T VAL> struct constant_value
{
static const T value = VAL;
};
typedef constant_value<bool,true> yes_type;
typedef constant_value<bool,false> no_type;
template<typename T> struct is_fundamental : public no_type{};
// Create a macro for convenience
#define DECLARE_FUNDAMENTAL(X) \
template<> struct is_fundamental<X> : public yes_type{}
// Specialize for all fundamental types
DECLARE_FUNDAMENTAL(void);
DECLARE_FUNDAMENTAL(bool);
DECLARE_FUNDAMENTAL(signed char);
DECLARE_FUNDAMENTAL(unsigned char);
// ... lots more similar specializations ...
DECLARE_FUNDAMENTAL(wchar_t);
DECLARE_FUNDAMENTAL(float);
DECLARE_FUNDAMENTAL(double);
DECLARE_FUNDAMENTAL(long double);
// Prevent this macro from polluting everything else...
#undef DECLARE_FUNDAMENTAL
This is essentially what is required to create such an object-type object. Note that an attacker can specialize a type property to be true for a non-fundamental type, although this is the case for most things as well. Anyway.
Then you can use the above to create a more functional looking thing. For example, using the boost :: type_traits :: is_fundamental class, you can create the following:
template<typename T>
bool isFundametal(const T&)
{
return boost::type_traits::is_fundamental<T>::value;
}
Since template specialization can be inferred from parameters, you can call this isFundamental function without explicitly specifying the type. For example, if you write isFundamental (5), it will implicitly call isFundamental <int> (5), which will return true. Note, however, that if you create such a function, it will prevent you from checking for void. You could create a function that would have no parameters for such a case, but then the type would not be inferred and therefore no prettier than just using boost :: type_traits :: is_fundamenta <T> :: value and so on one might just use it in this case.
a source to share