I am looking for a way to identify primitives types in a template class definition.
I mean, having this class :
template
class A{
void
The following example (first posted in comp.lang.c++.moderated) illustrates using partial specialisation to print things differently depending on whether or not they are built-in types.
// some template stuff
//--------------------
#include <iostream>
#include <vector>
#include <list>
using namespace std;
// test for numeric types
//-------------------------
template <typename T> struct IsNum {
enum { Yes = 0, No = 1 };
};
template <> struct IsNum <int> {
enum { Yes = 1, No = 0 };
};
template <> struct IsNum <double> {
enum { Yes = 1, No = 0 };
};
// add more IsNum types as required
// template with specialisation for collections and numeric types
//---------------------------------------------------------------
template <typename T, bool num = false> struct Printer {
void Print( const T & t ) {
typename T::const_iterator it = t.begin();
while( it != t.end() ) {
cout << *it << " ";
++it;
}
cout << endl;
}
};
template <typename T> struct Printer <T, true> {
void Print( const T & t ) {
cout << t << endl;
}
};
// print function instantiates printer depoending on whether or
// not we are trying to print numeric type
//-------------------------------------------------------------
template <class T> void MyPrint( const T & t ) {
Printer <T, IsNum<T>::Yes> p;
p.Print( t );
}
// some test types
//----------------
typedef std::vector <int> Vec;
typedef std::list <int> List;
// test it all
//------------
int main() {
Vec x;
x.push_back( 1 );
x.push_back( 2 );
MyPrint( x ); // prints 1 2
List y;
y.push_back( 3 );
y.push_back( 4 );
MyPrint( y ); // prints 3 4
int z = 42;
MyPrint( z ); // prints 42
return 0;
}
UPDATE: Since C++11, use the is_fundamental template from the standard library:
#include <type_traits>
template<class T>
void test() {
if (std::is_fundamental<T>::value) {
// ...
} else {
// ...
}
}
// Generic: Not primitive
template<class T>
bool isPrimitiveType() {
return false;
}
// Now, you have to create specializations for **all** primitive types
template<>
bool isPrimitiveType<int>() {
return true;
}
// TODO: bool, double, char, ....
// Usage:
template<class T>
void test() {
if (isPrimitiveType<T>()) {
std::cout << "Primitive" << std::endl;
} else {
std::cout << "Not primitive" << std::endl;
}
}
In order to save the function call overhead, use structs:
template<class T>
struct IsPrimitiveType {
enum { VALUE = 0 };
};
template<>
struct IsPrimitiveType<int> {
enum { VALUE = 1 };
};
// ...
template<class T>
void test() {
if (IsPrimitiveType<T>::VALUE) {
// ...
} else {
// ...
}
}
As others have pointed out, you can save your time implementing that by yourself and use is_fundamental from the Boost Type Traits Library, which seems to do exactly the same.