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的直接基数.这个假设真的错了吗?
经过一番挖掘 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 来说意味着“不”(至少,如果当前标准也这么说的话:供读者练习)。