主要观点:
- 讨论了 C++中“不良格式但无需诊断(IFNDR)”的概念,常见的意外来源是违反“单一定义规则(ODR)”,通过基于编译时开关定义不同的类或函数。
- 以
Widget
类为例,若不同的.cpp
文件根据编译时开关有不同的定义,链接时会违反 ODR。 - 类型别名不受 ODR 限制,可在不同翻译单元中有不同定义。
- 通过模板
WidgetT
实现了不同调试版本和非调试版本的Widget
,并通过外部模板声明和别名来选择使用。 - 模板的实现不在头文件中,需要显式实例化模板以触发代码生成。
- 当客户端使用
widget.h
头文件时,可根据调试设置选择不同的Widget
版本,但不同版本之间的交互可能导致链接错误,如在类中使用Widget
或在全局函数中返回Widget
时。
关键信息:
Widget
类中根据编译时开关有不同的Log
方法定义。WidgetT
模板有调试和非调试版本,分别有Logger
或std::monostate
成员。- 需显式实例化
WidgetT
模板。 - 客户端使用的
Widget
别名不同可能导致链接错误,类或全局函数中使用Widget
也可能引发 ODR 违规。
重要细节:
[msvc::no_unique_address]
属性用于告知编译器可将空对象折叠为无,在非调试时消失。- 若一个客户端暴露的类使用
Widget
,不同调试设置的客户端可能对该类中Widget
的版本有不同理解,引发 ODR 违规。 - 提到类似技术可用于处理
wchar_t
的多种可能定义,并给出相关阅读链接。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。