为什么我可以使用不相交的模板参数选项来重载函数,而不是 class?

Why can I overload a function with disjoint template parameter options, but not a class?

这样编译:

template <typename T, typename T2> void foo() { std::cout << "in foo() for two types." << std::endl; }
template <typename T, T Value>     void foo() { std::cout << "in foo() for a type and a value." << std::endl; }

这不是(GCC 4.9.3 with -std=c++11):

template <typename T, typename T2> class A { A() { std::cout << "in A::A() for two types." << std::endl; } };
template <typename T, T Value>     class A { A() { std::cout << "in A::a() for a type and a value." << std::endl; } };

错误是:

a.cpp:6:23: error: template parameter ‘class T2’
 template <typename T, typename T2> class A { A() { std::cout << "in A::A() for two types." << std::endl; } };
                       ^
a.cpp:7:42: error: redeclared here as ‘T Value’
 template <typename T, T Value>     class A { A() { std::cout << "in A::a() for a type and a value." << std::endl; } };
                                          ^

第二种重载对我来说似乎非常合理,不会有歧义,因为类型和值是不相交的。那为什么不允许呢?

这就是 class 模板的工作方式。您从一个主要模板开始:

template <class T, class U> struct A;

然后你可以专攻它。所有专业必须与主要专业相匹配:

template <class T> struct A<T, T> {...}; // OK
template <class T> struct A<T> {...}; // nope

目前的定义很简单:首先查找主要的,然后根据部分排序规则选择专业化。

为了满足您的需求,选择正确的 class 模板的语言将发生相当大的变化。特别是考虑到您可以简单地实现您想要的:

template <class T, T V>
struct A<T, std::integral_constant<T, V>> {...};