Can I specify exactly what kind of arguments a template can receive? For example, I’d like to create a template that can only be instantiated with classes that are or extend class A. In Java, generics support this with:
class B<T extends A> { }
Can something similar be achieved with templates in C++?
template <typename T (?)> class B { }
There are two ways to do this.
First, through a hidden dummy template parameter that uses
std::enable_ifwith astd::is_base_of<A, T>::valueas condition. If the latter expression evaulates tofalse, then the nestedtypedoes not exist instd::enable_if. If you were using this on overloaded functions, SFINAE then means “substitution failure is not an error”, and the overload in question would be removed from the set of viable functions. HOwever in this situation, there is no other class template to match your call, and then you do get a compile-time error.SFINAE is a very subtle mechanism and easy to get wrong. E.g. if you have multiple class specializations with different SFINAE conditions, you have to make sure that they are all non-overlapping, or else you get an ambiguity.
Second, you can do a simple
static_assertwith astd::is_base_of<A,T>::valueinside the body of the class. The advantage of this method is that you also specify a more readable error message compared to the SFINAE method. A disadvantage is that you always get an error, and you cannot silently suppress this particular template and select another one. But overall I think this method is recommended in your case.As was pointed out in the comments, you can use either a decent C++11 compiler (VC++ 2010 or later, gcc 4.5 or later) or the Boost or TR1 libraries to get the
<type_traits>functionality. Note however that thestd::is_base_of<A, A>::valueevaluates totrue, but the oldboost::is_base_of<A, A>::valueused to evalute tofalse.