类构造函数使用extern template的跨编译器编译差异问题
Clang与GCC对模板构造函数extern template声明的兼容性问题
问题说明
为缩短编译时间,尝试用extern template减少模板构造函数的实例化次数,编写代码如下:
#include <iostream> namespace Hello { class Test { template<typename T> Test(T& t) { std::cout << t << std::endl; } }; } extern template Hello::Test::Test<int>(int&);
使用Clang编译时触发以下错误:
<source>:13:30: error: qualified reference to 'Test' is a constructor name rather than a type in this context 13 | extern template Hello::Test::Test<int>(int&); | ^ <source>:13:34: error: expected unqualified-id 13 | extern template Hello::Test::Test<int>(int&); | ^
但相同代码可在GCC中正常编译。
原因分析
这是由于Clang与GCC对C++标准中模板构造函数的extern template声明语法的实现差异:
- GCC已实现该语法支持,允许通过
类名::构造函数名<T>(参数)的形式声明模板构造函数的外部实例化特化。 - Clang的解析器目前处理该语法时,会将限定名中重复的类名(
Hello::Test::Test)解析为普通构造函数而非模板构造函数标识,因此触发语法错误。
尽管C++标准理论上允许该写法,但Clang尚未完成对该语法特性的支持。
兼容方案
要让代码同时兼容Clang和GCC,可将模板构造函数改为静态模板成员函数,通过静态函数创建对象,即可正常使用extern template:
#include <iostream> namespace Hello { class Test { private: Test() = default; // 私有默认构造函数 public: template<typename T> static Test create(T& t) { Test obj; std::cout << t << std::endl; return obj; } }; } // 声明create<int>的外部实例化 extern template Hello::Test Hello::Test::create<int>(int&);
该方案既达到了减少模板实例化次数的目的,又能在Clang和GCC中正常编译。
内容的提问来源于stack exchange,提问作者user1466885
相关产品推荐
相关产品推荐

