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.