由于标头中的匿名命名空间导致ODR冲突



通过阅读标准,我无法确定以下代码是否违反了ODR:

// a.h
#ifndef A_HEADER_FILE
#define A_HEADER_FILE
namespace {
int v;
}
inline int get_v() { return v; }
#endif // A_HEADER_FILE
// a.cpp
#include "a.h"
void f() {
int i = get_v();
// ...
}
// b.cpp
#include "a.h"
void g() {
int i = get_v();
// ...
}

(来源:https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file(

假设get_v()在每个翻译单元中引用不同的变量,因此它违反了ODR

这个答案是:内联函数和外部链接说内联放松了ODR,所以我不确定为什么这仍然是一个错误?

有人能把我链接到标准中指定的位置吗?这是否是ODR违规?

一个inline函数可以有多个定义(C++17[basic.def.odr]/6(。这就是inline函数可以用来防止odr冲突的意义。但是,inline函数的多个定义必须彼此一致。具体来说,[basic.def.odr]/6.2说:

D的每个定义中,根据6.4查找的相应名称应指D定义中定义的实体,或应指同一实体[…][某些例外情况]

get_v的多个定义引用变量v,但v未在get_v中定义。因此,要求get_v的每个定义引用相同的变量v。事实并非如此,因为每个翻译单元具有不同的v。因此,违反了ODR。

最新更新