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



下面的程序是否违反了一个定义规则?

// 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.cppm2.cpp都有自己的版本,因此不会违反ODR。另一方面,bar()只是一个普通的老式内联函数,它恰好调用了2个不同的foo。所以它违反了ODR,对吧?

更新:以前我在foo的定义中有宏,改变了它返回的值,m1m2在包括foo.hpp之前对宏的定义不同。(在前面的示例中,g++将生成一个二进制文件,输出(i+j)的值与您期望的值不同)但实际上,即使foo()的主体相同,该程序也违反了ODR。

这确实违反了ODR。参见3.2/5,其中讨论了外部内联函数(bar):

在每个定义D,对应的名称,查找根据3.4,应指D定义内定义的实体,或指同一实体……

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

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

正如你所说,即使所有版本的foo()都是相同的,这也是一种违反,因为它们仍然是不同的函数。

相关内容

  • 没有找到相关文章

最新更新