为什么编译器在定义类似的模板特化时不会出错?

Kir*_*lev 10 c++ templates compiler-errors template-specialization

比较班级template专业化的程序是什么?关于这一点,标准没有详细说明(或者我错过了正确的地方).
我的问题与决定在实例化期间使用什么专业化无关.请不要对此发表评论.问题是关于比较专业化以确定是否已定义特定专业化.

考虑以下示例代码:

template <class x1, class x2>
struct CoreTemplate { };

template <class x1, class x2>
struct CoreTemplate<x1*, x2*> { int spec; CoreTemplate() { spec = 1; } };

template <class x1, class x2>
struct CoreTemplate<x2*, x1*> { int spec; CoreTemplate() { spec = 2; } };

int main(int argc, char* argv[])
{
    CoreTemplate<int*, int*> qq;
    printf("var=%d.\r\n", qq.spec);
}
Run Code Online (Sandbox Code Playgroud)

当我尝试使用MSVC编译此代码时,我在main函数内部实例化尝试时出错:

cpptest1.cxx(15):错误C2752:' CoreTemplate<x1,x2>':多个部分特化与模板参数列表匹配

对我来说,为尝试声明相同的模板特化而发出错误更合乎逻辑.我认为上述专业化没有任何区别.

那么,有没有人知道比较模板特化的规则?文章,链接,书籍等也会有所帮助.

Jer*_*fin 5

该标准具体说明只有在您尝试实例化模板时才会发生这种情况(§14.5.4.1/ 1):

当在需要实例化类的上下文中使用类模板时,有必要确定是使用主模板还是部分特化之一生成实例化.[强调补充]

不幸的是,如果不讨论如何确定在实例化期间使用哪种特化,则无法回答您的其余问题.这是标准中的文本(从上面的摘录继续):

这是通过将类模板特化的模板参数与部分特化的模板参数列表进行匹配来完成的.

  • 如果找到一个匹配的特化,则从该特化生成实例化.
  • 如果找到多个匹配专业化,则使用偏序规则(14.5.4.2)来确定其中一个专业化是否比其他专业化更专业化.如果没有一个专门化比所有其他匹配专业化更专业化,那么类模板的使用是不明确的,并且程序是不正确的.

因此,它甚至从未试图将模板直接相互比较.相反,它试图找到一个与给定参数匹配的特化.如果多个匹配,它会尝试根据部分排序规则选择最专业的一个.如果两者都不比另一个更专业,那么实例化是不明确的,并且编译失败.

现在,这些专业化都不会被使用,这当然是正确的,因为总是存在歧义 - 如果要么匹配,另一个显然匹配同样好.但是,编译器根本不需要检测或诊断它.在这个确切的情况下(基本上相同的专业化)可能很容易,但几乎可以肯定其他情况会更加困难,因此(显然)委员会认为编译器甚至不必尝试.

  • 我认为这一切都归结为一个定义规则.模板只能有一个定义,而部分特化是模板.所以,我们真的留下了两个特化是否被认为是同一个模板的问题,我在标准中找不到明确定义的那个.通过研究g ++的行为,如果模板参数列表相同,则认为两个特化是相同的模板,而忽略特定的名称. (2认同)