C++ template WTF
by Leandro Lucarella on 2010- 07- 25 23:22 (updated on 2010- 07- 25 23:22)- with 0 comment(s)
See this small program:
template<typename T1> struct A { template<typename T2> void foo_A() {} }; template<typename T> struct B : A<T> { void foo_B() { this->foo_A<int>(); // line 10 } }; int main() { B<int> b; b.foo_B(); return 0; }
You may think it should compile. Well, it doesn't:
g++ t.cpp -o t t.cpp: In member function ‘void B<T>::foo_B()’: t.cpp:10: error: expected primary-expression before ‘int’ t.cpp:10: error: expected ‘;’ before ‘int’
Today I've learned a new (horrible) feature of C++, foo_A is an ambiguous symbol for C++. I've seen the typename keyword being used to disambiguate types before (specially when using iterators) but never a template. Here is the code that works:
template<typename T1> struct A { template<typename T2> void foo_A() {} }; template<typename T> struct B : A<T> { void foo_B() { this->template foo_A<int>(); // ^^^^^^^^ // or: A<T>::template foo_A<int>(); // but not simply: template foo_A<int>(); } }; int main() { B<int> b; b.foo_B(); return 0; }
Note how you have to help the compiler, explicitly saying yes, believe me, foo_A is a template because it has no clue. Also note that the template keyword is only needed when A, B and A::foo_A are all templates; remove the template<...> to any of them, and the original example will compile flawlessly, so this is a special special special case.
Yeah, really spooky!
In D things are more natural, because templates are not ambiguous (thanks to the odd symbol!(Type) syntax), you can just write:
class A(T1) { void foo_A(T2)() {} } class B(T) : A!(T) { void foo_B() { foo_A!(int)(); } } void main() { B!(int) b; b.foo_B(); }
And all works as expected.