使用LLVM-Clang隐式实例化私有c++模板时的链接器错误
Linker error with implicit instantiation of private C++ template with LLVM-Clang
免责声明:我知道模板通常在头文件中实现。
我有一个c++模板相关的问题。我的代码在Windows下使用MSVC构建,但在Mac OSX下不使用LLVM-Clang,但我不确定哪个是错误的。
下面是一个简单的测试用例,由三个源文件组成:main.cpp
#include "templ.h" int main() { templ(1); return 0; }
templ.h
template<typename T> T templ(const T&);
templ.cpp
#include "templ.h" template<typename T> T templ(const T& t) { return t; } //explicit instantiation template int templ(const int&); //implicit instantiation void f() { templ(1); }
正如你所看到的,我希望函数模板的实现是私有的(即隐藏在.cpp文件中)。为此,我必须在与其定义相同的翻译单元中实例化我的模板。在上面的示例中,我只实例化了templ<int>
。我敢说,这是不寻常的,但却是完美的c++。
实际上,这段代码使用这两个编译器构建。但是,如果我注释掉显式实例化,只留下隐式实例化,编译器的行为就会不同。MSVC成功构建,但LLVM-Clang失败,出现以下链接器错误:
Undefined symbols for architecture x86_64:
"int templ<int>(int const&)", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
此外,该错误仅在启用优化(例如-02
)时发生。
标准对此有何规定?这是LLVM-Clang的已知行为/错误吗?
我的LLVM-Clang版本是:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
如果这是重复的,很抱歉。选择正确的关键词是非常困难的。
这是正常的,也是预料之中的。
14模板函数模板、类模板的成员函数、变量模板或类模板的静态数据成员应在其隐式实例化的每个翻译单元中定义(14.7.1),除非相应的特化在某些翻译单元中显式实例化(14.7.2);不需要诊断。
对于您的情况,这意味着当templ
的显式实例化被删除时,编译器可以
- 正常生成实例化,因为在同一TU中隐式实例化;或
- 内联对
templ
的调用,不生成任何外部可用的实体。
任何一种行为都是被允许的。如果您确保在某处有显式实例化,则两者都将生成有效的目标代码。如果你不这样做,你可能会或可能不会得到一个错误,这是你自己的错。
相关文章:
- 静态数据成员的问题-修复链接错误会导致编译器错误
- Visual Studio mkl_link_tool.exe链接错误
- C++ 实现模板单例类时出现链接错误
- 使用类模板的方法链接错误
- MySQL C++连接器链接错误
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 运行 C++ 单元测试时LNK2005链接错误
- 对 CMake 中'cudaRegisterLinkedBinary'链接错误的未定义引用?
- 链接错误,包括我创建的相同头文件 - C++
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 使用标头保护的多个定义链接错误
- 链接错误:未定义对 stdscr 和 wgetch 的引用
- 使用 Vivek 的 Vcam / 捕获源过滤器构建/链接错误
- 升压program_options中的链接错误
- 使用 g++ 预处理器进行替换会导致链接错误
- 在调试配置中编译工作正常,但发布会给出链接错误
- 相邻矩阵设置链接错误
- 包含常量变量并包含在多个文件中的标头的链接错误
- C++链接错误,我理解但无法解决
- 是什么导致macOS Mojave上的GoogleTest链接错误