GCC/VS2008:模板化基类从自身派生时函数调用的不同行为

use*_*715 13 c++ inheritance gcc templates visual-studio-2008

以下代码适用于Visual Studio 2008,但不适用于GCC/G ++ 4.3.4 20090804.根据C++标准,哪种行为是正确的?

template <int N>
struct A : A<N-1> {};

template <>
struct A<0> {};

struct B : A<1> {};

template <int N>
void Func(const A<N> &a) {}

int main()
{
    A<1> a;   //is derived from A<0>
    Func(a);  //vs2008: ok, g++: ok
              //Comeau: ok

    B b;      //is derived from A<1>
    Func(b);  //vs2008: ok, g++: error, no matching function for call to Func(B&)
              //Comeau: error: no instance of function template "Func" matches the
              //        argument list. The argument types that you used are: (B).

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我重载Func()

void Func(const A<0> &a) { std::cout << '0'; }
void Func(const A<1> &a) { std::cout << '1'; }
Run Code Online (Sandbox Code Playgroud)

总是调用后者(如预期的那样).所以我也希望用N = 1调用模板化函数,因为A <1>是B的直接基数.这个假设真的错了吗?

Jan*_*Jan 4

经过一番挖掘 N3035 后,我在第 14.9.2.1.4 节中发现了这一点:

如果 P 是一个类,并且 P 具有 simple-template-id 形式,则转换后的 A 可以是推导 A 的派生类。同样,如果 P 是指向 simple-template-id 形式的类的指针,则转换后的 A 可以是指向推导的 A 所指向的派生类的指针。

然而在 14.9.2.1.5 中,它说:

仅当类型推导失败时才考虑这些替代方案。如果它们产生多个可能的推导 A,则类型推导失败。

情况是这样的: 和A<1>A<0>被视为 的基类B

我想这对 Visual Studio 来说意味着“不”(至少,如果当前标准也这么说的话:供读者练习)。