简体   繁体   English

在这种情况下如何防止 ODR 违规?

[英]How to prevent ODR violations in this case?

disclaimer: this question is about prevention of unintended naming collisions, and make sure the following code fail to compile/link.免责声明:这个问题是关于防止意外的命名冲突,并确保以下代码无法编译/链接。

[edit] actually I'd be happy with something preventing this to compile/link, or something that solves this, like anonymous namespaces. [编辑] 实际上,我很高兴有一些东西可以阻止它编译/链接,或者一些可以解决这个问题的东西,比如匿名名称空间。 But anonymous namespaces aren't supposed to go inside headers.但是匿名命名空间不应该在标头内 go 。

// Class1.h
// --------
namespace SomeLargeLib {
struct S {
  int a;
  S() { a = 1; }
};
}

// Class1.cpp
// ----------
#include "Class1.h"

void foo() { SomeLargeLib::S s; }

// Class2.h
// --------
namespace SomeLargeLib {
struct S {
  int a;
  S() { a = 2; }
};
}

// Class2.cpp
// -----------
#include "Class2.h"

int main() {
  SomeLargeLib::S s;
  return s.a; // returns 1 !!
}

What happens here is that the ctor S::S has two inline definitions, so the linker is allowed to assume all definitions are the same and pick any one.这里发生的是 ctor S::S 有两个内联定义,因此允许 linker 假设所有定义都相同并选择任何一个。 Note that moving the S::S ctors outside of the classes results in a linker error as they are no longer inline.请注意,将 S::S ctors 移到类之外会导致 linker 错误,因为它们不再是内联的。

Anyway, since we shouldn't have anonymous namespaces in headers (see C++ Core Guidelines), what should be done to prevent such ODR violations?无论如何,既然我们不应该在标头中使用匿名命名空间(请参阅 C++ 核心指南),那么应该如何防止此类 ODR 违规行为? A linker error would be perfect but the standard says no diagnostic is needed for ODR violations. linker 错误将是完美的,但标准表示 ODR 违规不需要诊断。

ODR violation are extremely hard to detect automatically, that's why it is ill formed no diagnostic required. ODR 违规非常难以自动检测,这就是为什么它是病态的,不需要诊断。

However, if your goal is to prevent and detect such cases, simply use modules with a strong ownership.但是,如果您的目标是防止和检测此类情况,只需使用具有强所有权的模块即可。 The model completely prevent most (if not all) ODR violations that are hard to detect. model 完全防止了大多数(如果不是全部)难以检测的 ODR 违规。

Example:例子:

class1.ixx : class1.ixx

export module class1;
namespace SomeLargeLib {
export struct S {
  int a;
  S() { a = 1; }
};
}

class2.ixx : class2.ixx

export module class2;
namespace SomeLargeLib {
export struct S {
  int a;
  S() { a = 2; }
};
}

test1.cpp : test1.cpp

import class1;
import <iostream>;

void fun() {
    SomeLargeLib::S a;
    std::cout << a.a; // 1
}

test2.cpp : test2.cpp

import class2;
import <iostream>;

void fun() {
    SomeLargeLib::S a;
    std::cout << a.a; // 2
}

And the great thing is that you could link test1.cpp and test2.cpp together in the same binary.最棒的是,您可以在同一个二进制文件test2.cpp test1.cpp在一起。 No collision ever happen.永远不会发生碰撞。

However, a compiler error is emitted for test3: test3.cpp :但是,会为 test3: test3.cpp发出编译器错误:

import class1;
import class2; // error: name SomeLargeLib::S already exists, can't import both

Those use cases are supported in MSVC already today.这些用例今天已经在 MSVC 中得到支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 标头中的“const”和“constexpr”变量是否应为“内联”以防止违反 ODR? - Should `const` and `constexpr` variables in headers be `inline` to prevent ODR violations? 如何在标头中使用未命名的命名空间会导致ODR违规? - How would use of unnamed namespaces in headers cause ODR-violations? 有没有办法检测内联函数ODR违规? - Is there a way to detect inline function ODR violations? 使用调试断言时避免ODR违规 - Avoiding ODR violations when using debug asserts 关于ODR违规和模板变量 - About ODR-violations and template variables 可以使用不同的别名模板来解决跨库的潜在ODR违规问题吗? - Can differing alias templates resolve potential ODR violations across libraries? C ++模块是否会导致ODR违规? - Do C++ modules make ODR violations absent? 为什么编译器不会在同一个翻译单元中警告ODR违规 - Why doesn't the compiler warn against ODR violations in the same translation unit 是否需要一个实现来诊断同一 TU 内同一显式专业化的重复定义的 ODR 违规? - Is an implementation required to diagnose ODR-violations of duplicated definitions of the same explicit specialization within the same TU? 在源文件中声明 function 模板时,我是否应该防止违反 ODR? - Should I protect against ODR violations when declaring function templates in source files?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM