Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC/VS2008: Different behaviour of function call when templated base class is derived from itself

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?

like image 209
user287715 Avatar asked Mar 06 '10 12:03

user287715


1 Answers

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).

like image 157
Jan Avatar answered Oct 15 '22 13:10

Jan