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 .
这确实违反了ODR.参见3.2/5,它讨论的是外部内联函数(bar):
在D的每个定义中,根据3.4查找的相应名称,应指D中定义的实体,或者指同一实体......
在这种情况下bar指的是两个不同的版本foo,因此违反了规则.
是的,这个定义bar()确实违反了一个定义规则.您正在创建多个定义,每个定义调用一个名为的不同函数foo().
如你所说,即使所有版本foo()都相同,也会违反,因为它们仍然是不同的功能.