为什么通用模板方法定义与模板类专门化不匹配?

aby*_*s.7 7 c++ templates c++11

我有以下代码:

template <class T, class U = T>
class A {
  public:
    void f();
};

template <class T>
class A<T, T> {
  public:
    void f();  // Unaltered method.

    // Some differences.
};

template <class T, class U>
void A<T, U>::f() {}

int main() {
  A<int> a;
  a.f();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

clang++ -std=c++11 test.cc给我一个错误:undefined reference to 'A<int, int>::f()'

为什么提供的方法定义f()不适用于该类A<int, int>

Pra*_*ian 6

主类模板template <class T, class U = T> class A和部分特化template <class T> class A<T, T>是两个不同的模板定义.定义它们之后,无论何时引用类模板名称A,都将始终考虑主模板和所有部分特化.

无论何时A使用单个模板参数或同一类型的两个参数进行实例化,它都会形成与您提供的特化相匹配的更好的匹配,并且不考虑主模板.

在您的示例中,由于您提供的部分特化,如果您尝试A使用单个模板参数或两个相同类型的实例化,则无论是否使用默认模板参数,都无法匹配主模板.

当然,解决方案是提供定义 A<T, T>::f()

template <class T>
void A<T, T>::f() {}
Run Code Online (Sandbox Code Playgroud)

编辑:
在存在部分特化的情况下,匹配它们的规则由(来自N3797)§14.5.5.1/ 1 [temp.class.spec.match]给出

当在需要实例化类的上下文中使用类模板时,有必要确定是使用主模板还是部分特化之一生成实例化.这是通过将类模板特化的模板参数与部分特化的模板参数列表进行匹配来完成的.
- 如果找到一个匹配的特化,则从该特化生成实例化.
- 如果找到多个匹配专业化,则使用偏序规则(14.5.5.2)来确定其中一个专业化是否比其他专业化更专业化....
- 如果未找到匹配项,则从主模板生成实例化.

在您的示例中,第一个规则适用,编译器甚至没有达到第3个规则.