Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does template class instantiation work together with class inheritance?

Tags:

c++

Code

I have the following snippets of 2 classes with a separate source and header file. The derived class is a template class.

handler.h

class BaseHandler {
public:
    BaseHandler(){}
    BaseHandler(const std::string& directive);
    virtual ~BaseHandler();
    virtual bool operator()();
private:
    const std::string m_directive;
};

template<typename C>
class DirectiveHandler : public BaseHandler {
public:
    DirectiveHandler(const std::string& directive);
    ~DirectiveHandler();
    bool operator()() override;
private:
    std::vector<C> m_configurations;
};

handler.cpp

#include "handler.h"

BaseHandler::BaseHandler(const std::string& directive) : m_directive(directive) {};

BaseHandler::~BaseHandler(){};

template<typename C>
DirectiveHandler<C>::DirectiveHandler(const std::string& directive) :
    BaseHandler(directive) {};

template<typename C>
bool DirectiveHandler<C>::operator()(){ return true; };

main.cpp

#include "handler.h"

template class DirectiveHandler<double>;    //explicit template instantiation

int main(int argc, char *argv[]){
....

To my understanding I need to instantiate the template after it has been defined, this can happen either implicitly (leave out template class DirectiveHandler<double>;) or explicitly. I'm assuming that implicit instantiation fails due to the separation of definition and declaration in the respective source and header file.

With the snippet of main.cpp above I have the following warnings:

  1. warning: explicit template instantiation DirectiveHandler<double> will emit a vtable in every translation unit

  2. warning: instantiation of function DirectiveHandler<double>::operator() required here, but no definition available

If change template class DirectiveHandler<double> to extern template class DirectiveHandler<double>;both warnings dissapear. I do understand why warning 2 is cleared, because the template class resides in handler.cpp. I fail to see how it clears warning 1 as well.

Question

Why does the addition of the extern keyword clear warning 1 (see above)?

like image 859
Bruno Hendrickx Avatar asked Oct 17 '22 08:10

Bruno Hendrickx


1 Answers

I assume, you are compiling your code with CLang? (To the best of my knowledge, it is CLang warning, unless g++ started to emit it as well).

On any rate, the answer to the question as asked (I only have to assume that OP understands everything else) is the simple fact that template class DirectiveHandler<double>; - which is implicit template instantiation definition, which produces vtbls and such. (The fact that the warning is emitted for .cpp file might be actually a bug, but OP doesn't ask about it).

On the other hand, extern template class DirectiveHandler<double>; is not a definition. It is a declaration, which doesn't on itself trigger vptr's generation - and thus you see no warning.

like image 164
SergeyA Avatar answered Oct 20 '22 16:10

SergeyA