17

我是否违反了以下程序的单一定义规则?

// 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的 s。所以它违反了ODR,对吧?

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

4

2 回答 2

8

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

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

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

于 2011-10-31T14:48:57.230 回答
6

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

正如您所说,即使所有版本foo()都相同,也将是违规行为,因为它们仍然是不同的功能。

于 2011-10-31T14:41:41.653 回答