我有以下2个类的摘要,带有单独的源文件和头文件。派生类是模板类。
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[]){
....
据我了解,我需要在模板定义后实例化,这可以隐式发生(省去template class DirectiveHandler<double>;
或显式发生)。
我假设隐式实例化由于在各自的源文件和头文件中定义和声明的分离而失败。
使用上面的 main.cpp 片段,我有以下警告:
warning: explicit template instantiation DirectiveHandler<double> will emit a vtable in every translation unit
warning: instantiation of function DirectiveHandler<double>::operator() required here, but no definition available
如果将template class DirectiveHandler<double>
更改为extern template class DirectiveHandler<double>;
,则警告均消失。我确实理解为什么会清除警告2,因为模板类位于 handler.cpp 中。我也看不到它如何清除警告1。
为什么添加extern
关键字会清除警告1(请参见上文)?
答案 0 :(得分:3)
我认为,您正在使用CLang编译代码? (据我所知,这是CLang警告,除非g ++也开始发出警告)。
无论如何,所问问题的答案(我只需要假设OP能够理解所有其他内容)就是一个简单的事实,即template class DirectiveHandler<double>;
-这是隐式模板实例化定义,它产生{{1} }等。 (对于vtbl
文件发出警告的事实实际上可能是一个错误,但是OP并没有询问它。)
另一方面,.cpp
不是定义。这是一个声明,它本身不会触发extern template class DirectiveHandler<double>;
的生成-因此您不会看到任何警告。