通常没有必要限制模板可以实例化的类型。模板可以用给定的类型编译(并且可以正常工作),或者不能(并且在程序员不做任何努力的情况下产生编译器错误)。
如果您需要设置限制,通常这些类型有一些共同点,可以通过一些已经可用的类型特征(标准库,boost::type_traits)来描述,或者您可以为它们创建一个新的类型特征。
例如,这是一个只允许整数类型的模板类,使用std::numeric_limits 对其进行检查(如果您编写自己的数字类型,您可以对其进行专门化,以便它也适用于您的新整数类型)。 static_assert 仅适用于 C++0x,如果不可用,请使用 BOOST_STATIC_ASSERT 或其他技巧。
#include <limits>
#include <string>
template <class T>
class X
{
static_assert(std::numeric_limits<T>::is_integer, "X can be only instantiated with integer types");
//...
};
int main()
{
X<int> xi;
X<char> xc;
//X<double> xd;
//X<std::string> xs;
}
如果您只计划支持少数没有共同点的任意类型(从您的假设示例中可以明显看出),一种方法是使用类型列表。再次提升可能会使任务变得更容易,但这是您可以自己滚动的方式(这只是进行到一半,需要额外的工作才能使声明类型列表更漂亮)。
struct no_type {};
template <class T, class U = no_type>
struct t_list
{
typedef T head;
typedef U tail;
};
//trait to check if two types are identical
template <class T, class U>
struct is_same
{
static const bool value = false;
};
template <class T>
struct is_same<T, T>
{
static const bool value = true;
};
//compile-time recursion to check if T matches any type in list L
template <class T, class L>
struct in_type_list
{
static const bool value =
is_same<T, typename L::head>::value || in_type_list<T, typename L::tail>::value;
};
//terminates recursion
template <class T>
struct in_type_list<T, no_type>
{
static const bool value = false;
};
template <class T>
class X
{
typedef t_list<double, t_list<int, t_list<char> > > allowed_types; //double, int, char
//poor man's static_assert
typedef int check_type [in_type_list<T, allowed_types>::value ? 1 : -1];
//...
};
int main()
{
X<char> xc;
X<int> xi;
X<double> xd;
//X<float> xf;
}