Visual Studio 中(基于字符的)STL(流)容器的编译错误

2023-11-23

这基本上是同一个问题[SO]:C2491:'std :: numpunct :: id':不允许定义dllimport静态数据成员[关闭],但考虑以下事实:

  • (在我看来)这是一个完全有效的问题(根据[SO]:如何创建一个最小的、完整的、可验证的示例),真不知道为什么有些用户有种想关闭它的冲动
  • 标记为解决方案的答案提供了修复错误的指南(一般而言),但是不适用就目前的情况而言,当然,没有解决它,

请不要关闭它或将其标记为重复项(至少,在没有仔细阅读和理解它的情况下)。

main.cpp:

#include <sstream>


//#define THROW_C2491
#if defined(THROW_C2491)
typedef int CharType;
#else
typedef char CharType;
#endif


int main() {
    std::basic_stringstream<CharType> stream;
    CharType c = 0x41;
    stream << c;
    return 0;
}

代码稍作修改(简化),编译失败if THROW_C2491被定义为:

xlocnum(294): error C2491: 'std::numpunct<_Elem>::id': definition of dllimport static data member not allowed

Output:

E:\Work\Dev\StackOverflow\q048716223>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" amd64

E:\Work\Dev\StackOverflow\q048716223>
E:\Work\Dev\StackOverflow\q048716223>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\bin\amd64\cl.exe" /GS /W3 /Zc:wchar_t /ZI /Gm /Od /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo -c "src\main.cpp"
main.cpp

E:\Work\Dev\StackOverflow\q048716223>echo %errorlevel%
0

E:\Work\Dev\StackOverflow\q048716223>
E:\Work\Dev\StackOverflow\q048716223>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\bin\amd64\cl.exe" /GS /W3 /Zc:wchar_t /ZI /Gm /Od /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo -c "src\main.cpp" /D "THROW_C2491"
main.cpp
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(294): warning C4273: 'id': inconsistent dll linkage
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(120): note: see previous definition of 'public: static std::locale::id std::numpunct<int>::id'
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(120): note: while compiling class template static data member 'std::locale::id std::numpunct<_Elem>::id'
        with
        [
            _Elem=CharType
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(1261): note: see reference to function template instantiation 'const _Facet &std::use_facet<std::numpunct<_Elem>>(const std::locale &)' being compiled
        with
        [
            _Facet=std::numpunct<CharType>,
            _Elem=CharType
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(1255): note: while compiling class template member function 'std::ostreambuf_iterator<_Elem,_Traits> std::num_put<_Elem,std::ostreambuf_iterator<_Elem,_Traits>>::do_put(_OutIt,std::ios_base &,_Elem,bool) const'
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>,
            _OutIt=std::ostreambuf_iterator<CharType,std::char_traits<CharType>>
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\ostream(305): note: see reference to class template instantiation 'std::num_put<_Elem,std::ostreambuf_iterator<_Elem,_Traits>>' being compiled
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\ostream(291): note: while compiling class template member function 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator <<(int)'
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>
        ]
e:\work\dev\stackoverflow\q048716223\src\main.cpp(16): note: see reference to function template instantiation 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator <<(int)' being compiled
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\istream(939): note: see reference to class template instantiation 'std::basic_ostream<_Elem,_Traits>' being compiled
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\sstream(574): note: see reference to class template instantiation 'std::basic_iostream<_Elem,_Traits>' being compiled
        with
        [
            _Elem=CharType,
            _Traits=std::char_traits<CharType>
        ]
e:\work\dev\stackoverflow\q048716223\src\main.cpp(14): note: see reference to class template instantiation 'std::basic_stringstream<CharType,std::char_traits<_Elem>,std::allocator<_Elem>>' being compiled
        with
        [
            _Elem=CharType
        ]
c:\install\x86\microsoft\visual studio community\2015\vc\include\xlocnum(294): error C2491: 'std::numpunct<_Elem>::id': definition of dllimport static data member not allowed
        with
        [
            _Elem=CharType
        ]

E:\Work\Dev\StackOverflow\q048716223>echo %errorlevel%
2

Notes:

  • 一切都是VStudio 2015

开始笔记:

  • 我在用VStudio 社区 2015 (v14.0.25431.01更新3)。版本在这里很重要,因为标准头文件可能会因版本而异(并且行号可能不同)
  • Created [MSDN]:Visual Studio 中 STL(流)容器的编译错误

方法:

  1. 快速(浅层)调查

    On VStudio IDE double click, on the 2nd note in the Output window (after attempting to compile the file), and from there repeated RClicks on relevant macros, and from the context menu choosing Go To Definition (F12):

    • xlocnum (#120):(注释是原始文件/行的一部分)

      __PURE_APPDOMAIN_GLOBAL _CRTIMP2_PURE static locale::id id; // unique facet id
      
    • yvals.h:(#494):

           #define _CRTIMP2_PURE _CRTIMP2
      
    • crtdefs.h (#29+):

      #ifndef _CRTIMP2
          #if defined CRTDLL2 && defined _CRTBLD
              #define _CRTIMP2 __declspec(dllexport)
          #else
              #if defined _DLL && !defined _STATIC_CPPLIB
                  #define _CRTIMP2 __declspec(dllimport)  // @TODO - cfati: line #34: Here is the definition
              #else
                  #define _CRTIMP2
              #endif
          #endif
      #endif
      

    正如所见,__declspec(dllimport)定义在第 #34 行。重复该过程_DLL宏,没有结果。发现于[MSDN]:预定义宏:

    _DLL定义为 1,当/MD or /MDd(多线程 DLL)编译器选项已设置。否则,未定义。

    我想到了两种可能的方法(都导致了成功的构建):

    • Use static的版本显像管运行时 ([MSDN]:/MD、/MT、/LD(使用运行时库))。我不认为这是一个可行的选择,特别是当该项目包括.dlls(确实如此):坏事可能会发生(例如[SO]:在 MSVC 2013 上链接到 protobuf 3 时出错,甚至更糟糕的情况可能会在运行时发生)
    • 手动#undef _DLL (in main.cpp, before any #include)。这是一个蹩脚的解决方法(gainarie)。它构建得很好,但是篡改这些东西可能(并且很可能会)触发未定义的行为在运行时

    这两个选项都不是完全令人满意,因此:

  2. 更深入一点

    试图进一步简化事情(main.cpp):

    #include <sstream>
    
    
    //typedef unsigned short CharType;  // wchar_t  unsigned short
    #define CharType unsigned short
    
    
    int main() {
        std::basic_stringstream<CharType> stream;
        CharType c = 0x41;
        stream << c;
        return 0;
    }
    

    Notes:

    • 已更换typedef by #define(消除新类型定义的复杂性)
    • 切换到unsigned short这是wchar_t的定义 (/Zc:wchar_t-)以避免任何可能的字体大小 / 结盟差异


    “编译”上面的代码[MSDN]:/E(预处理到标准输出) and [MSDN]:/EP(在没有 #line 指令的情况下预处理到标准输出)(以便警告/错误仅引用当前文件中的行号):

    • 生成的预处理文件(使用上面的每个标志):~1MB+ (~56.5k lines)
    • 文件中唯一的区别是#define (wchar_t vs. unsigned short)在最后的某个地方
    • 编译这些文件(令人震惊:))产生了相同的结果:wchar_t一个编译时unsigned short因同样的错误而失败
    • Added some #pragma message statements (yes, they are handled by the preprocessor, but still) in the file that fails (before each warning/note), noticed some difference between the 2 #defines, but so far unable to figure out why 1
    • While browsing the generated file(s), noticed a template<> struct char_traits<char32_t> definition, so I gave it a try, and it worked (at least the current program compiled) 1 (and, as expected sizeof(char32_t) is 4). Then, found [MSDN]: char, wchar_t, char16_t, char32_t


    Notes:

    • 虽然这解决了我的current问题(仍然不知道为什么),将不得不试一试end goal
    • 1 Although I looked over the file, I didn't see any template definitions targeting only the "privileged" types (e.g. I didn't see anything that would differentiate wchar_t, signed char or char32_t from unsigned short for example), so I don't know (yet) why it works for some types but not for others. This is an open topic, whenever I'll get new updates, I will share them

底线:

As 经验地发现,在使用时允许使用以下类型char based STL容器:

  • char
  • unsigned char
  • signed char
  • wchar_t
  • char16_t
  • char32_t
  • unsigned short (/Zc:wchar_t- only )

最后的注释:

  • 我将合并任何有用的东西(例如comments)在答案中

@EDIT0:

  • 基于 @IgorTandetnik 的回答[MSDN]:Visual Studio 中 STL(流)容器的编译错误,尽管仍然有一点雾气:

    • unsigned char and signed char
    • 之间的区别static and dynamic C++ RTLib


    我将接受这个作为答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Visual Studio 中(基于字符的)STL(流)容器的编译错误 的相关文章

  • Windows 窗体中的切换开关控件

    我正在设计一个拨动开关控制使用CheckBox 但目前我的控件只能画一个圆圈 如何绘制如下图所示的圆形形状 以及如何根据控件的值更改圆圈的位置以表示选中和未选中的状态 如下图所示 这是我的代码 public class MyCheckBox
  • 如何在 ASP.Net Core 6 Web Api 中依赖注入 Microsoft Graph 客户端

    我正在尝试使用 ASP Net Core 6 设置 Web api 以便用户可以到达我的端点 然后我使用特权帐户在 Teams 中执行一些工作 我认为我没有正确连接 DI 部分 因为在向 Teams 发出请求时出现以下错误 MsalUiRe
  • 使用 c11 标准和 clang 来使用 strcpy_s

    我正在运行 OS X Sierra 并尝试编译一个使用的 c 程序strcpy s 但是我安装的 clang 编译器使用的是 c99 标准 但是据我读到的 https embeddedgurus com barr code 2017 08
  • 忽略父进程中的信号

    我正在尝试实现一个 shell 程序 我希望 shell 程序忽略 SIG INT ctrl c 但在我的程序中 子进程也会忽略 SIG INT 信号 但它不应该这样做 因为 exec 应该将子进程带到另一个程序 并且该程序默认情况下应该处
  • 使用 R.Net 版本 1.5.5 创建 REngine 实例

    我正在尝试创建一个 Hello World 示例R Language using R Net版本1 5 5 从 NuGet 加载 不幸的是 我见过的在线示例都不起作用 这就是我所做的 已安装Microsoft R Open 3 2 4 增强
  • 在“delete this;”语句期间发生了什么?

    请考虑以下代码 class foo public foo foo void done delete this private int x 以下两个选项中发生了什么 并且有效吗 选项1 void main foo a new foo a gt
  • ASP.NET MVC 数据注释属性 Range 从另一个属性值设置

    您好 我的 Asp net MVc 模型中有以下内容 测试模型 cs public class TestModel public double OpeningAmount get set Required ErrorMessage Requ
  • ICSharpCode.Decompiler + Mono.Cecil -> 如何为单个方法生成代码?

    我可以使用 Mono Cecil 和 ICSharpCode Decompiler 生成类型或程序集的代码 但是 如果我尝试为单个方法生成代码 我将收到错误 对象引用未设置为对象的实例 你们能给我任何关于这个的提示吗 提前感谢您的所有帮助
  • std::istringstream >> 使奇怪的行为加倍

    下面的代码打印0在 mac osx 上使用 clang 其他地方都会打印5 clang https ideone com mVgpzS gcc https ideone com oZ0hy6 include
  • 隐式转换和编译器的不同行为

    Motivated by this question https stackoverflow com q 51972738 5800831 I created the following code struct X X int struct
  • Makefile:如何正确包含头文件及其目录?

    我有以下 makefile CC g INC DIR StdCUtil CFLAGS c Wall I INC DIR DEPS split h all Lock o DBC o Trace o o cpp DEPS CC o lt CFL
  • autofac 中的条件组件注册

    是否可以根据其他组件的状态有条件地注册组件 就像是 ContainerBuilder RegisterConditionally
  • 使用 itextSharp 5.3.3 对 Pdf 文档进行数字签名和验证

    我正在尝试使用 iTextSharp 5 3 3 在服务器 c 上进行数字签名和验证 pdf 文档 我使用 DigiSign 在线工具 生成了 Pfx 文件 然后使用 Windows 生成证书 cer 文件
  • 如何声明返回相同类型的 Func Delegate 的 Func Delegate?

    我想编写一个方法 该方法可以完成一些工作 并最终返回另一个与原始方法具有相同签名的方法 这个想法是根据前一个字节值顺序处理字节流 而不进行递归 通过这样调用它 MyDelegate executeMethod handleFirstByte
  • 从 ASP.NET Web API 返回 HTML

    如何从 ASP NET MVC Web API 控制器返回 HTML 我尝试了下面的代码 但由于未定义 Response Write 而出现编译错误 public class MyController ApiController HttpP
  • 更改为通用接口对性能的影响

    我使用 Visual Studio 使用 C NET 开发应用程序 ReSharper 在我的方法原型中经常建议我用更通用的类型替换输入参数的类型 例如 如果我仅在方法主体中使用带有 foreach 的列表 则使用 List 和 IEnum
  • 我们可以向 ServicePointManager.SecurityProtocol 添加四个协议吗?

    我想支持从 ssl3 到 tls 1 2 的所有安全协议 但是在网上搜索时我发现代码为 ServicePointManager SecurityProtocol SecurityProtocolType Ssl3 SecurityProto
  • 如何获取 EF 中的实体更改增量?

    我只需要获取已更改字段的列表 数据存储区是 ssce 因此没有可用的触发器 EF 是否支持获取列表或构建通用组件 根据上下文的类型和生成的实体 您可以通过多种不同的方式来完成此操作 如果对象继承自 Entity 或 POCO 您可以使用Ob
  • 在运行时生成可执行文件

    好吧 所以我想知道如何创建一个程序 该程序创建第二个程序 就像大多数压缩程序如何创建自解压自可执行文件一样 但这不是我需要的 假设我有 2 个程序 每个都包含一个类 我将使用一个程序来修改类并用数据填充类 第二个文件将是一个也具有该类的程序
  • 使用 System.Windows.Forms.Timer.Start()/Stop() 与 Enabled = true/false

    假设我们在 Net 应用程序中使用 System Windows Forms Timer 在计时器上使用 Start 和 Stop 方法与使用 Enabled 属性之间有什么有意义的区别吗 例如 如果我们希望在进行某些处理时暂停计时器 我们

随机推荐