具有可变参数的外部模板无法编译

时间:2013-04-18 07:55:20

标签: c++ templates c++11 variadic-templates

我尝试创建一个带有可变参数的extern模板,如:

extern template<typename... XS> void log( XS... xs );

但是gcc 7.2没有编译它,并显示错误:

error: expected unqualified-id before ‘<’ token

我在c ++ 11中检查gcc状态,extern模板应该有效,不是吗?

1 个答案:

答案 0 :(得分:7)

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)生成代码,链接器会抱怨未定义的引用。