c++ - 为什么在尝试创建 std::numpunct 的实例时出现链接错误衍生物?
问题描述
我正在尝试使用std::basic_stringstream<char16_t>
基于 UTF16 的std::numpunct
. 但是尝试创建即使是最简单的可能导数也会std::numpunct<char16_t>
在链接阶段失败。这是代码:
#include <locale>
struct my_punct : public std::numpunct<char16_t> {};
int main()
{
my_punct n;
}
以下是链接错误(使用 g++ 7.2.0)(现场测试):
$ g++-7 test0.cpp -o test
/tmp/cc0oWPhL.o: In function `std::numpunct<char16_t>::numpunct(unsigned int)':
test0.cpp:(.text._ZNSt8numpunctIDsEC2Ej[_ZNSt8numpunctIDsEC5Ej]+0x36): undefined reference to `std::numpunct<char16_t>::_M_initialize_numpunct(__locale_struct*)'
/tmp/cc0oWPhL.o: In function `my_punct::~my_punct()':
test0.cpp:(.text._ZN8my_punctD2Ev[_ZN8my_punctD5Ev]+0x18): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0x8): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0xc): undefined reference to `std::numpunct<char16_t>::~numpunct()'
collect2: error: ld returned 1 exit status
如果我更改char16_t
为char
,则链接成功完成。那么,我在这里做错了什么?我需要一些额外的库来链接吗?
作为一个健全的检查,我已经尝试 grepping GCC 安装_ZTVSt8numpunctIDsE
,但它没有给出任何结果。但是 grepping_ZTVSt8numpunctIcE
确实找到了libstdc++.so.6.0.24
。这是否意味着我在 libstdc++ 中发现了一个错误?
解决方案
这是因为没有专门的类的支持实现。当您使用模板时会发生什么,编译器会为该特定用途生成一个符号。如果已经有一个预定义且完全模板化的实现,那么编译器可以自己定义,但前提是它在编译文件试图使用它时看到模板化实现。如果它看不到它,那么它只是创建符号,让它未定义,并期望稍后链接它。
作为一个简单的例子......
在 Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
在 Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
在 main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
main.cpp
这种行为的原因是在任何可以看到它的地方都不存在模板化实现。但是,当所有内容都链接时,链接器会看到存在“int add(int, int)”,因此这是允许的。
如果您拥有模板,则可以将(模板化)实现添加到包含模板声明的 .h 文件中。这样编译器就知道如何在编译时生成符号和定义。为了修复上面的例子,我们可以在 Template_Add.h 中添加以下代码:
template< class T >
T add(T first, T second){
return first + second;
}
...然后包括“Template_Add.h”在内的任何东西都可以为任何试图使用模板的东西生成自己的实现。
如果您不拥有该模板,那么您能做的最好的事情就是找到一种方法来使用受支持的模板专业化。在这种情况下,最好将您的(或 typedef)char16_t
转换为 a short
,然后查看是否有效。
推荐阅读
- javascript - 将输入转换为十六进制和二进制
- reactjs - 钩子 useState 是 formik - React
- android - 取消选择 RecyclerView 单元格,但点击它之外的任何地方
- python - 计算灰度图像的直方图
- javascript - vue js中的vue路由器动态路由与strapi headless CMS - 路由器链接和href标签抛出错误
- python - 在 Palantir Foundry 代码存储库中定义 Pandas UDF 的正确方法是什么
- javascript - PNG图像作为按钮
- vb.net - 在 windowsform 上显示托管在 localhost 中的 WebApp
- python - 在databricks上转换to_timestamp python sql的问题
- r - 在 dplyr 中动态更新数据框的多列