Hello
I am looking for a way to identify primitives types in a template class definition.
I mean, having this class :
template<class T>
class A{
void doWork(){
if(T isPrimitiveType())
doSomething();
else
doSomethingElse();
}
private:
T *t;
};
Is there is any way to "implement" isPrimitiveType().
-
// 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.
Ben : Yes, but what I want is specilize my class *for all* primitives types :/Ferdinand Beyer : See my edited answer. -
Boost TypeTraits has plenty of stuff.
-
Assuming by 'Primitive Type' you mean the built in types you can do a series of template specializations. Your code would become:
template<class T> struct A{ void doWork(); private: T *t; }; template<> void A<float>::doWork() { doSomething(); } template<> void A<int>::doWork() { doSomething(); } // etc. for whatever types you like template<class T> void A<T>::doWork() { doSomethingElse(); } -
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; }Ben : this helped, thanks ! -
It cannot be done exactly the way you asked. Here is how it can be done :
template<class T> class A{ void doWork(){ bool isPrimitive = boost::is_fundamental<T>::value; if(isPrimitive) doSomething(); else doSomethingElse(); } private: T *t; };You may get a warning if you put the value of isPrimitive directly inside the if statement. This is why i introduced a temporary variable.
-
Yet another similar examples:
#include <boost/type_traits/is_fundamental.hpp> #include <iostream> template<typename T, bool=true> struct foo_impl { void do_work() { std::cout << "0" << std::endl; } }; template<typename T> struct foo_impl<T,false> { void do_work() { std::cout << "1" << std::endl; } }; template<class T> struct foo { void do_work() { foo_impl<T, boost::is_fundamental<T>::value>().do_work(); } }; int main() { foo<int> a; a.do_work(); foo<std::string> b; b.do_work(); }BenoƮt : Your version is a bit more efficient that mine, but i considered that it did not compensate for the readability cost.Anonymous : Probably there are even nicer ways of doing this. The above was quickly hacked in vim to test the idea...
0 comments:
Post a Comment