匿名命名空间和一个定义规则

Lam*_*eek 16 c++ namespaces one-definition-rule

我是否违反了One Definition Rule并使用以下程序?

// foo.hpp
#ifndef FOO_HPP_
#define FOO_HPP_

namespace {
   inline int foo() {
       return 1;
   }
}

inline int bar() {
    return foo();
}
#endif
//EOF
Run Code Online (Sandbox Code Playgroud)

// m1.cpp

#include "foo.hpp"

int m1() {
    return bar();
}

//EOF
Run Code Online (Sandbox Code Playgroud)

// m2.cpp

#include "foo.hpp"

int m2() {
    return bar();
}

//EOF
Run Code Online (Sandbox Code Playgroud)

最后

// main.cpp
#include <iostream>

int m1();
int m2();

int main(int, const char* [])
{
    int i = m1();
    int j = m2();

    std::cout << (i+j) << std::endl;
    return 0;
}

// EOF
Run Code Online (Sandbox Code Playgroud)

在上面的,请注意,foo()在一个匿名的命名空间中定义,因此,我希望每一个翻译单元m1.cpp,并m2.cpp会得到自己的版本,所以没有违反ODR的.另一方面,bar()它只是一个简单的旧内联函数,恰好称为2个不同的foos.所以它违反了ODR,对吧?

更新: 以前我在定义中有宏,foo它改变了它返回的值,m1并且m2在包含之前每个宏都有不同的定义foo.hpp.(并且使用前面的示例,g++将生成一个二进制文件,其输出(i+j)值不是您期望的值.)但事实上,即使主体foo()相同,此程序也会违反ODR .

Mar*_*k B 8

这确实违反了ODR.参见3.2/5,它讨论的是外部内联函数(bar):

在D的每个定义中,根据3.4查找的相应名称,应指D中定义的实体,或者指同一实体......

在这种情况下bar指的是两个不同的版本foo,因此违反了规则.


Mik*_*our 6

是的,这个定义bar()确实违反了一个定义规则.您正在创建多个定义,每个定义调用一个名为的不同函数foo().

如你所说,即使所有版本foo()都相同,也会违反,因为它们仍然是不同的功能.