After seeing this question When is a C++ template instantiation type checked? , and wondering myself for quite some time the same thing I started to play with code to assimilate the knowledge. The answer gives clear and correct explanation. It mentions two-phase name lookup and the fact that the end of translation unit is also considered a point of instantiation for function templates. However I observed different behavior when using automatic return type deduction:
This is like the original code. It is correct and works as explained in the linked post:
class A;
class B;
template <class T> auto foo() -> T * {
A *pa = nullptr; // ignore pa being `nullptr`.
return static_cast<T *>(pa);
}
auto test() { return foo<B>(); }
class A {};
class B : public A {};
When using automatic return type deduction for the template foo
, the definitions of A
and B
must appear before the instantiation point of foo
:
Not working:
class A;
class B;
template <class T> auto foo() { // automatic return type deduction
A *pa = nullptr;
return static_cast<T *>(pa);
}
auto test() { return foo<B>(); }
class A {};
class B : public A {};
The error by gcc (4.9 and 5.2.1):
error: invalid static_cast from type ‘A*’ to type ‘B*’
Clang gives a similar error
Working:
class A;
class B;
template <class T> auto foo() { // automatic return type deduction
A *pa = nullptr;
return static_cast<T *>(pa);
}
class A {};
class B : public A {};
auto test() { return foo<B>(); }
Why it is happening? Why is that the rule about the end of compilation unit beeing considered a point of instantiation doesn't make the template instantiation legitimate anymore?