Full template instance, enforced in C ++ template inheritance?

We all know that the C ++ class template does not generate member functions that are not used like below:

template<typename T>
class A
{
    public:
    void WrongFunction(T t);
    void RightFunction(T t);
};

template<typename T>
void A<T>::WrongFunction(T t)
{
    std::vector<T> v;
    auto a = "abc" - v;
}

template<typename T>
void A<T>::RightFunction(T t)
{
    std::cout << "Success" << std::endl;
}

int main()
{
    A<int> a;
    a.RightFunction(2);
    //a.WrongFunction(1);
    return 0;
}

      

Since the WrongFunction is not primarily called, no actual code is generated for it and therefore no compilation error occurs.

Now, let's introduce an abstract base class that defines the interface for class A (basically template inheritance):

template<typename T>
class Base
{
    public:
    virtual void RightFunction(T t) = 0;
    virtual void WrongFunction(T t) = 0;
};

template<typename T>
class A : Base<T>
{
    public:
    void WrongFunction(T t) override;
    void RightFunction(T t) override;
};

template<typename T>
void A<T>::WrongFunction(T t)
{
    std::vector<T> v;
    auto a = "abc" - v;
}

template<typename T>
void A<T>::RightFunction(T t)
{
    std::cout << "Success" << std::endl;
}

int main()
{
    A<int> a;
    a.RightFunction(2);
    //a.WrongFunction(1);
    return 0;
}

      

Suddenly the compiler refuses to work:

prog.cc: When creating "void A :: WrongFunction (T) [with T = int] ': prog.cc:39:1: required here prog.cc:24:20: error: no match for" operator- " (operand types: "const char [4]" and 'std :: vector>') auto a = "abc" - v;

My understanding of the workflow is basically I say by instantiating A. Fine, the compiler then finds the template declaration for A (note that A is not a class; A<SomeType>

is.). Wow, it depends Base<int>

. Ok, the compiler then finds the template declaration for Base, hooks the int to the position held by T - now we have the declaration for the class Base<int>

, but the definition is not created - after all, we did not provide a template to define the generation for Base<SomeType>

, and no one ever created an instance Base<int>

or called a function on an instance. It's great. The compiler then expands the declaration Base<int>

and generates the declarationA<int>

... Wait, on the next line RightFunction is called. So the compiler finds the template definition for RightFunction for A and plugs in the specific type int and generates the member function definition for A.

Since WrongFunction is never called (no specialization is involved in any explicit instance), the compiler shouldn't even try to generate code for A<int>

:: WrongFunction --- my question is, what the heck is going on?

Compiler: gcc 4.9.2

Thank.

+3


source to share


1 answer


From N3337, ยง14.7.1 / 10 [temp.inst]

An implementation must not implicitly create a function template, member template, non-virtual member function, member class, or class template static data member that does not require instantiation. It is unknown if the implementation implicitly implements an instance of the virtual member function of the class template if the virtual member function was not otherwise instantiated. ...



Thus, implementation needs to instantiate the virtual member function, even if you never call it.

In practice, this is likely to always be the case, since when instantiating a class template, the compiler also needs to instantiate a vtable for that class, which must be populated with the addresses of the virtual member functions.

+4


source







All Articles