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

C++ GCC/VS2008:模板基类从自身派生时函数调用的不同行为,c++,visual-studio-2008,inheritance,gcc,templates,C++,Visual Studio 2008,Inheritance,Gcc,Templates,以下代码适用于Visual Studio 2008,但不适用于GCC/G++4.3.4 20090804。根据C++标准,哪种行为是正确的?< /P> template <int N> struct A : A<N-1> {}; template <> struct A<0> {}; struct B : A<1> {}; template <int N> void Func(const A<N> &

以下代码适用于Visual Studio 2008,但不适用于GCC/G++4.3.4 20090804。根据C++标准,哪种行为是正确的?< /P>
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;
}
模板
结构A:A{};
模板
结构A{};
结构B:A{};
模板
void Func(常数A&A){}
int main()
{
A;//是从
Func(a);//vs2008:ok,g++:ok
//科莫:好的
B;//是从
Func(b);//vs2008:ok,g++:错误,对Func(b&)的调用没有匹配的函数
//Comeau:错误:没有函数模板“Func”的实例与
//参数列表。您使用的参数类型是:(B)。
返回0;
}
如果我用


void Func(const A&A){std::cout在N3035中进行了一些挖掘之后,我在第14.9.2.1.4节中发现了这一点:

如果p是一个类且p具有形式简单模板id,则转换后的a可以是推导出的a的派生类。同样,如果p是指向形式简单模板id的类的指针,则转换后的a可以是指向推导出的a所指向的派生类的指针

然而,在14.9.2.1.5中,它说:

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

情况是这样的:
A
A
都被认为是
B
的基类


我想这对Visual Studio来说意味着一个否定(至少,如果当前的标准说的是相同的:读者练习)。

在ISO/IEC 14882中,它几乎是相同的(14.8.2.1):

  • 如果P是一个类,并且P具有表单模板id,那么a可以是一个 导出的A的导出类。 同样,如果P是指向类的指针 对于表单模板id,A可以是 指向指向的派生类的指针 由A
只有在类型扣除时才考虑这些替代 否则就会失败。如果他们屈服 一个以上的可能推导出一个 类型扣除失败


所以我同意Jan的观点。这里的任何人都不会?

也不会使用Comeau Online进行编译。在第二种情况下,您希望N是什么(因为b可以转换为A和A)?我想这只是MSVC++的另一个扩展。@UncleBens,哇,我还没有看到
B
也继承了
A
!好眼力:)注意直接调用
void f(A);void f(A);B;f(B);
将成功,因为
A
继承
A
A
被认为是更好的匹配。但是在演绎过程中,这并不重要,正如@UncleBens所说:编译器将产生两个演绎并拒绝模板。是的,您可以调用
Func
指定模板参数,它将工作。(例如:
Func(b) 
)。以这种方式指定的原因是什么?
void Func(const A<0> &a) { std::cout << '0'; }
void Func(const A<1> &a) { std::cout << '1'; }