views:

209

answers:

2

The following code works with Visual Studio 2008 but not with GCC/G++ 4.3.4 20090804. Which behaviour is - according to the C++ standard - correct?

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;
}

If I overload Func() with

void Func(const A<0> &a) { std::cout << '0'; }
void Func(const A<1> &a) { std::cout << '1'; }

always the latter one is called (as expected). So I would also expect the templated function to be called with N=1 because A<1> is direct base of B. Is this assumption really wrong?

+3  A: 

After some digging through N3035, I found this in section 14.9.2.1.4:

If P is a class and P has the form simple-template-id, then the transformed A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class pointed to by the deduced A.

However in 14.9.2.1.5, it says:

These alternatives are considered only if type deduction would otherwise fail. If they yield more than one possible deduced A, the type deduction fails.

Which is the case: both A<1> and A<0> are considered base classes for B.

I guess this means a no for Visual Studio (at least, if the current standard says the same: exercise for the reader).

Jan
+1 for the digging :)
neuro
A: 

In ISO/IEC 14882 it's nearly the same (14.8.2.1):

  • If P is a class, and P has the form template-id, then A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form template-id, A can be a pointer to a derived class pointed to by the deduced A.

These altenatives are considered only if type deduction would otherwise fail. If they yield more than one possible deduced A, the type deduction fails.

So I agree with Jan. Anybody here who does not?

What could be the reason that it was specified this way?