ODR和内部链接

ODR and internal linkage

假设我在一个程序中有两个编译单元,每个编译单元都声明了一个非内联函数,具有相同的签名,但实现不同,例如

// a.cpp
namespace internal {
    int foo(int a) {
        return a+1;
    }
}

int main() {
}

// b.cpp
namespace internal {
    int foo(int b) {
        return b+2;
    }
}

Compiling/linking 这个(g++ 4.8.3 with -std=c++11),我得到一个错误

b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'

这是意料之中的,因为据我所知,这只是违反了 one definition rule:

One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries).

现在,将 namespace internal 更改为未命名的命名空间,错误消失了。直觉上,这对我来说很有意义,因为我正在改变函数 external to internal linkage:

Any of the following names declared at namespace scope have external linkage unless the namespace is unnamed or is contained within an unnamed namespace (since C++11): variables and functions not listed above (that is, functions not declared static [...]) ...

[A]ll names declared in unnamed namespace or a namespace within an unnamed namespace, even ones explicitly declared extern, have internal linkage.

但是,我无法在一个定义规则中找到任何免除具有内部链接的函数的内容。因此,我的问题是:我的直觉推理是否正确,或者我是否仍然违反具有内部链接的函数的单一定义规则(并且 compiler/linker 只是不再报告)?另外,标准(或cppreference.com :))在哪里说是否可以?

n4713

§6.5 Program and linkage [basic.link]

A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:

(2.1) — When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

(2.2) — When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.

— When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.

这基本上是说(在未命名命名空间的情况下)来自 a.cpp 的名称 foo 和来自 b.cpp 的名称 foo 各自指代不同的实体。所以你没有同一个对象的两个定义,所以没有违反 ODR。