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()上記では、それは匿名の名前空間で定義されていることに注意してください。したがって、各翻訳単位は独自のバージョンを取得することを期待しているので、ODRの違反はありませんm1.cppm2.cpp一方、bar()は、たまたま2つの異なるを呼び出す単純な古いインライン関数fooです。それで、それはODRに違反しますよね?

更新: 以前は、定義にマクロがあり、fooそれが返す値を変更し、マクロを含める前にそれぞれ異なる方法でマクロm1を定義していました。(そして、その前の例では、期待した値以外の値で出力するバイナリを生成します。)しかし、実際には、このプログラムは、本体が同一であってもODRに違反します。m2foo.hppg++(i+j)foo()

4

2 に答える 2

8

これはODRに違反します。externインライン関数について話している3.2/5を参照してください(bar):

Dの各定義において、3.4に従って検索された対応する名前は、Dの定義内で定義されたエンティティを参照するか、同じエンティティを参照するものとします。

この場合bar、の2つの異なるバージョンを参照してfooいるため、ルールに違反しています。

于 2011-10-31T14:48:57.230 に答える
6

はい、この定義bar()は単一定義規則に違反しています。複数の定義を作成しており、それぞれが。と呼ばれる異なる関数を呼び出しますfoo()

foo()あなたが言うように、それらはまだ異なる機能であるため、すべてのバージョンが同一であっても違反になります。

于 2011-10-31T14:41:41.653 に答える