restricting c++ template usage to POD types
#include <type_traits>
template<typename T>
class myclass
{
static_assert(std::is_pod<T>::value, "T must be POD");
// stuff here...
};
The above will cause a compilation error if you pass a non-POD type as the template parameter. This solution requires C++11 for the <type_traits>
header and static_assert
keyword.
EDIT: You can also implement this in C++03 if your compiler supports TR1 (most do):
#include <tr1/type_traits>
template<typename T>
class myclass
{
static char T_must_be_pod[std::tr1::is_pod<T>::value ? 1 : -1];
// stuff here...
};
While the static_assert
probably suffices in most cases, using enable_if
and tag dispatch gives greater flexibility to the users of your class by the ways of SFINAE. Consider:
#include <type_traits>
#include <string>
#include <iostream>
template <typename T,
class=typename std::enable_if< std::is_pod<T>::value >::type>
struct myclass
{
typedef T value_type;
T data;
};
template <typename T>
void enjoy(T)
{
std::cout << "Enjoying T!" << std::endl;
}
template <typename T>
void enjoy(typename myclass<T>::value_type)
{
std::cout << "Enjoying myclass<T>::value_type!" << std::endl;
}
int main()
{
enjoy<int>(int()); // prints: Enjoying myclass<T>::value_type!
enjoy<std::string>(std::string()); // SFINAE at work - prints: enjoying T!
myclass<int> i; // compiles OK
//myclass<std::string> s; // won't compile - explicit instantiation w/non-POD!
}
Now if you remove the 2nd template argument from myclass
definition, and instead, like others have suggested, add a
static_assert(std::is_pod<T>::value, "POD expected for T");
inside the class, the second line in main()
will just fail to compile, triggering the static_assert.
That said, the errors from static_assert
are much more friendly to human observer, than those from the failed enable_if
. So, if static_assert
works for you, go for it. Otherwise, if you do need to be friendlier to generic programming around your class, consider adding an explanatory comment around enable_if
:
// POD expected for T
class=typename std::enable_if< std::is_pod<T>::value >::type>
unless everyone around you is C++11-fluent.
In real life, it's a good idea to explain why T must be POD both for static_assert
and for the comment texts.
If you have C++11 support std::is_pod should do exactly what you need. Use it with std::enable_if or with tag dispatch. For example something like this:
template <typename T, typename Enable = void>
class Test;
template<typename T>
class Test<T, typename std::enable_if<std::is_pod<T>::value, void>::type>
{};
int main() {
Test<int> t1;
//Test<std::string> t2; <-this will not compile
}