1

我有一个与Edge-case 相关的问题:当(仅)在专业化中反转模板参数的顺序时,是否可以达到非专业化版本?.

这是一个理论问题,涉及可能被认为写得不好的代码。但是,我想彻底了解模板语法。

假设两个模板特化在行内模板参数的顺序上有所不同template<...>,如下所示:

#include <iostream>

// Primary template
template<typename T1, typename T2, typename T3>
class A
{};

// Specialization #1
template<typename T2, typename T3>
class A<int, T2, T3>
{};

// Specialization #2
// Differs only in order of parameters in the "template<...>" line
template<typename T3, typename T2>
class A<int, T2, T3>
{};

int main()
{
    A<int, int, int> a; // <-- Compiler error: Ambiguous template specializations
    return 0;
}

在 Visual Studio 2010 编译器中,错误涉及不明确的模板专业化:'A<T1,T2,T3>' : more than one partial specialization matches the template argument list. could be 'A<int,T2,T3>' or 'A<int,T2,T3>'.

特别是,错误 is not 'A<int,T2,T3>' : class template has already been defined,这是当第二个特化与第一个特化是逐字符相同时产生的错误(即,模板参数的顺序不颠倒,并且读取template<typename T2, typename T3>,就像在特化 #1 中一样)。

但是,我认为template<...>模板专业化中的行中列出的参数顺序没有区别。具体来说,我认为特化中的template<...>行的目的只是将出现在特化类型名称 ( ) 中的标记识别A<int, T2, T3>为语法上有效的模板参数,而不是拼写错误。根据这个推理,template<...>模板特化的行中参数的顺序应该没有区别,并且两个在这些参数的顺序上逐字符不同的模板特化应该被视为重复定义,而不是模棱两可的特化。

如果我是正确的,那么 Visual Studio 2010 编译器是正确的,因为它在这种情况下会报告错误,但不正确的是它会将错误标识为模棱两可的专业化,而不是多重定义的专业化。

我对么?template<...>模板特化行中模板参数的顺序是否没有区别,因此两个相同的模板特化应该被视为相同模板特化的冗余定义,而不是两个不同但模棱两可的,模板专业化?

如果我不正确,那么上面代码中的两个专业化确实是不同的(即,不是多重定义的)。如果是这样,有人可以解释为什么它们不同以及客户端代码如何证明这种差异?

4

1 回答 1

1

部分特化的标识是传递给其模板的参数列表。模板类型参数名称表示特定的依赖类型,其标识包括它们在模板参数列表中的位置和模板参数列表的嵌套深度(即,如果成员模板是成员,则成员模板的列表比其封闭模板嵌套多一层类模板)。

这是有道理的,因为您需要处理两个不同的函数模板,它们彼此重载并且仅在模板参数顺序上有所不同。它们的实例化行为是不同的,因为它们的位置直接对应于函数模板调用的模板参数列表中的相应参数。

如果你重新排列它们的位置,参数列表会变得不同,因为不同的类型作为参数传递。所以你没有重新定义部分专业化。

于 2012-06-17T16:23:57.900 回答