我尝试使用可变参数创建一个外部模板,例如:
extern template<typename... XS> void log( XS... xs );
但是 gcc 7.2 没有编译它,并显示错误:
error: expected unqualified-id before ‘<’ token
我检查了 c++11 中的 gcc 状态,extern 模板应该可以工作,不是吗?
我尝试使用可变参数创建一个外部模板,例如:
extern template<typename... XS> void log( XS... xs );
但是 gcc 7.2 没有编译它,并显示错误:
error: expected unqualified-id before ‘<’ token
我检查了 c++11 中的 gcc 状态,extern 模板应该可以工作,不是吗?
该extern
关键字的作用与您的预期不同 - 当然,如果我正确理解您的预期。
该extern
关键字应用于模板的显式实例化,它可以防止编译器在处理某个翻译单元时为该模板隐式生成代码。根据 C++11 标准的第 14.7.2/2 段:
显式实例化有两种形式:显式实例化定义和显式实例化声明。显式实例化声明以
extern
关键字开头。
如果没有关键字,编译器将在每个包含对 的调用的翻译单元中extern
为(比如说)生成代码,并且该代码(对于所有翻译单元应该并且应该是相同的)最终将由链接器合并(链接器基本上会丢弃所有重复并只保留一个)。log(double, int)
log(double, int)
extern
关键字通过告诉编译器:“相信我,其他人会在其他地方实例化这个模板——你现在不需要这样做”,从而避免了编译时间的浪费。但这个承诺必须兑现。
例如,如果您有这个主模板:
template<typename... Xs> void log(Xs... xs);
然后你声明这个显式实例化:
extern template void log(int, double);
比您必须在某些翻译单元中具有相应的显式实例化:
template void log(int, double)
否则,编译器将永远不会为 生成代码log<int, double>(int, double)
,并且链接器将抱怨未定义的引用。