下面的程序是否违反了一个定义规则?
// foo.hpp
#ifndef FOO_HPP_
#define FOO_HPP_
namespace {
inline int foo() {
return 1;
}
}
inline int bar() {
return foo();
}
#endif
//EOF
和
// m1.cpp
#include "foo.hpp"
int m1() {
return bar();
}
//EOF
和
// m2.cpp
#include "foo.hpp"
int m2() {
return bar();
}
//EOF
最后和
// 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
在上面,请注意foo()
是在匿名命名空间中定义的,因此我希望每个翻译单元m1.cpp
和m2.cpp
都有自己的版本,因此不会违反ODR。另一方面,bar()
只是一个普通的老式内联函数,它恰好调用了2个不同的foo
。所以它违反了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()
都是相同的,这也是一种违反,因为它们仍然是不同的函数。