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

anonymous namespaces and the one definition rule(匿名命名空间和单一定义规则)

本文介绍了匿名命名空间和单一定义规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Am I violating the One Definition Rule with the following program?

// 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,对吧?

In the above, note that foo() is defined in an anonymous namespace, so I expect that each translation unit m1.cpp and m2.cpp will get its own version, so there is no violation of the ODR. On the other hand, bar() is just a plain old inline function which happens to call 2 different foos. So it violates the ODR, right?

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

Update: Previously I had macros in the definition of foo that changed the value it returned and each of m1 and m2 defined the macro differently before including foo.hpp. (And with that previous example, g++ would produce a binary that output (i+j) with a value other than what you would expect.) But in fact this program violates the ODR even if the body of foo() is identical.

推荐答案

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

This does violate the ODR. See 3.2/5 which is talking about extern inline functions (bar):

在D的每一个定义中,对应的名字,根据3.4,应指在D定义中定义的实体,或应指同一实体...

in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity...

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

In this case bar refers to two different versions of foo, thus violating the rule.

这篇关于匿名命名空间和单一定义规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:匿名命名空间和单一定义规则

基础教程推荐