5

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)?

Bruno Hendrickx
  • 354
  • 2
  • 14
  • Because now you do not have explicit template instantiation definition, just declaration. – SergeyA Jan 10 '19 at 16:26
  • 1
    @YSC, this closure was certainly incorrect. OP is asking a completely different question! I reopened it now. – SergeyA Jan 10 '19 at 16:29
  • 1
    @SergeyA And yet, [CNR](http://coliru.stacked-crooked.com/a/929cc5bb9e589302 "could not reproduce"). This is why we ask for a [mcve]. – YSC Jan 10 '19 at 16:34
  • Warning 1 is benign; the multiple vtables will be folded at link time. See also [here](https://stackoverflow.com/questions/16801222/out-of-line-virtual-method/16801276) – rustyx Jan 10 '19 at 16:35
  • 1
    @YSC, first off, CNR is different from a duplicate. Second off, your attempt at reproduction is **clearly** not correct - OP has multiple files and translation units, you have just one. I also have a feeling OP is using CLang, and if I am correct, this is one piece missing from original question. – SergeyA Jan 10 '19 at 16:36
  • @SergeyA 1. I failed to reproduce by applying the recommendation of the dup => this is a dup. 2. Warnings are emitted at compilation stage, which means its during the translation of *one* unit. 3. same thing with clang++. – YSC Jan 10 '19 at 16:39
  • 1
    @YSC what? OP is asking WHY adding `extern` removes the warning. What does it have to do with the dup? I completely fail to see your reasoning. Unfortunately, since OP seems to be less interested in this question than I am, I will refrain from further conversation, and any further actions on this question. – SergeyA Jan 10 '19 at 16:41
  • @SergeyA I overlooked a part of the question >_< Sh*t you're right, my bad. – YSC Jan 10 '19 at 16:54
  • @YSC :) glad we came to understanding! – SergeyA Jan 10 '19 at 18:41

1 Answers1

3

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.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I currently use the qt creator (ide). It uses Clang static code analyzer, but the code is compiled with g++-6. I admit that I do not fully understand all the details of using a base class together with template derived classes. This does answers my question. – Bruno Hendrickx Jan 11 '19 at 14:44