tags:

views:

80

answers:

2

Consider the following example:

template <typename T>
class A {
    public:
        void f() {
            cout << "A::f()\n";
        }
};

template<>
class A<int> {
};

template<typename T>
class B: public A<T> {
    public:
        void g() {
            cout << "B::g()\n";
            A<T>::f();
        }
};

int main() {
    B<int> b;     // (1)
    b.g();        // (2)

    return 0;
}

Obviously the call to A::f() inside B::g() will fail for int template type. My question is at what point does the call fail? At (1) or (2)? I thought it should be (1) because at that point the compiler creates a new class with the template type int and compiles it. That compilation should fail in f() correct?

+3  A: 

It fails at 2). Member function of templates are instantiated when called.

More precisely: When a class template is instantiated, the declaration of its member functions are instantiated, but not their definition. The definition is instantiated when the function is used.

Éric Malenfant
An interesting fact is that if you remove function `f` from all template definitions or explicit specializations of `A` in that TU, then the compiler is allowed to mark the definition of the member function `g` ill-formed and issue a diagnostic even if `B` is never used, because no valid specialization could ever be generated for that member function (`14.7/8`).
Johannes Schaub - litb
+4  A: 

It will fail at (2), and this is guaranteed by the standard. In section 14.7.1/1, it says instantiating a template class does not instantiate it's members definitions. That will only happen once the member is used.

If you remove (2) from the code, it will compile.

14.7.1/1 excerpt:
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions.

Emphasis mine.


Visual Studio's diagnosis is misleading. It will say see reference to class template instantiation 'B<T>' being compiled. What it means is not "I'm failing at the instantiation of B<T>", but "I'm failing at instantiating a member of the class B<T>"

GMan
The best thing is that VC only points to the line that instantiates `B`. Anyway, i should have learned by now to doubt VC and simply look it up first.
Georg Fritzsche