mardi 21 avril 2015

Full template instantiation forced in C++ template inheritance?

We all know a C++ class template does not generate member functions that are not used, as illustrated 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 called in main, there's no actual code 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: In instantiation of 'void A::WrongFunction(T) [with T = int]': prog.cc:39:1: required from here prog.cc:24:20: error: no match for 'operator-' (operand types are 'const char [4]' and 'std::vector >') auto a = "abc" - v;

My understanding of the work flow is, in main, I say create an instance of A. Fine, the compiler then finds the template declaration for A(note that A is not a class; A<SomeType> is.). Wow, it depends on Base<int>. Fine, the compiler then finds the template declaration for Base, plugs int into the position held by T - now we have the declaration for the class Base<int>, but no definition is generated - after all, we did not provide a template for definition generation for Base<SomeType>, and no one has ever created any instance of Base<int> or has called a function on the instance. That's fine. Then the compiler extends the declaration of Base<int> and generates the declaration of A<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 involved either; no explicit instantiation either), the compiler shouldn't even try to generate the code for A<int>::WrongFunction --- my question is, what the heck is going on?

Compiler: gcc 4.9.2

Thanks.

Aucun commentaire:

Enregistrer un commentaire