是具有预处理前分支实现的结构违反ODR
Are structs with preprocessor branched implementation an ODR violation?
在使用C和C 的项目中,.h
文件包含类型的定义。如果该定义取决于c
还是cpp
文件包含标题,我是否违反了一个定义规则?
// my_header.h
struct MyStruct
{
#ifdef __cplusplus
std::size_t member;
int surprise;
#else
unsigned member;
#endif
};
我知道ODR与不同的翻译单元有关,但是在"我的情况"中,不同的翻译单元最终对公共结构有不同的实现吗?我已经在生产代码中看到了这一点,最初我想知道在这种情况下,链接器在做什么。
有什么想法?
只要您使用一个编译器(C或C (,就不会有问题。标头文件的扩展名没关系。
但是,如果您将不同语言的翻译单元链接在一起,那么是的,您违反了ODR。
总的来说,这似乎真的很容易出错。我会给C 类型一个完全不同的名称。您可以使用宏在两者之间切换,也许可以在typedef
周围使用预处理器?
有两种情况:
-
所有包含标题(给定程序(的翻译单元均汇编为相同的语言(C或C (:
==>没有问题。
-
一些包括标头的翻译单元被翻译为C,有些则翻译为C 。
==>ODR违规。
但是,违反odr的行为是"不确定的行为",实际上,在标准中链接C和C 的标准中所定义的并不是那么多(除了一些模糊的建议&quot"它应该起作用。"。换句话说,如果您将C和C 链接在一起,则可能取决于实施的详细信息。
通常,如果您要编译32位(以便std::size_t
和unsigned
是相同的大小(,并且前提可能会逃脱。
是的,我有一个想法(嘿,对不起,您问(:请不要那样写代码。好吧,我保留正确的方法直到最后。但是就您的问题而言:是的,如果您同时将C和C 编译器作为构建过程的一部分,这将导致ODR违规。实际的文件扩展名可能无关紧要(可能会更改编译器的默认值,但是您的构建系统可以明确指定编译器的语言(。就是说,这是一个非常糟糕的主意,而且非常不寻常,因为C非常接近C 的适当子集,以至于简单地编写也可以使用C 编译器构建的C代码更为普遍。在具有C 组件的项目中,您将使用C 编译器,并且在纯C的项目中,您仍然可以使用该代码。因此,无论文件扩展名如何,只要给定的项目仅贴在一个编译器上,就可以。
// my_header.h
#ifdef __cplusplus
constexpr bool is_cpp = true;
#else
constexpr bool is_cpp = false;
#endif
struct cpp {
std::size_t member;
int surprise;
};
struct cc {
unsigned member;
};
template <bool CPP>
struct MyStructImpl : private std::conditional_t<cpp, cc, CPP>
{
};
using MyStruct = MyStructImpl<is_cpp>;
这可以在以相同方式和无条件定义的结构中保持尽可能多的代码,而不管宏观选项如何,并且将与宏相关的内容辩护至尽可能迟到。就工具和测试而言,这也是一个很大的胜利,例如您可以在不进行重新编译的情况下对两个版本的两个版本进行单元测试。
当您将多种语言链接在一起时,我尚不清楚违反ODR的含义; c 标准对您在 c 对象文件中可以定义的struct
s无话可说。因此,我们被迫在"汇编术语"(基于共同的实现(中回答,在这种情况下,答案(已经更雄辩地给出(是 wat 。
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- (ODR 使用问题)在不同文件中priority_queue名称相同的结构
- 为什么结构声明在C++中违反了 ODR
- 是具有预处理前分支实现的结构违反ODR
- 您可以在类型上使用结构化绑定违反ODR吗?
- 为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR