21

次の C++ コードの断片を考えてみましょう。

namespace
{
    void f()
    {
    }

    class A
    {
        void f()
        {
            ::f(); // VC++: error C2039: 'f' : is not a member of '`global namespace''
        }
    };
}

GCC はこれを問題なくコンパイルします。Visual C++ 2008 がコンパイルに失敗し、C2039 エラーが発生します。これら 2 つのコンパイラのうち、どちらが正しいですか? その「グローバル」 fを適切に参照する方法はありますか?

編集:ザックは試してみることを提案しましたが、両方のコンパイラで動作します。私には少し奇妙に見えます。

namespace
{
    void f()
    {
    }

    class A
    {
        void f();
    };
}

void A::f()
{
    ::f();
}
4

2 に答える 2

10

VC++2008はここでは間違っています。c ++ 03標準3.4.3.4によると:

単項スコープ演算子::(5.1)で始まる名前は、それが使用される変換単位で、グローバルスコープで検索されます。名前は、グローバル名前空間スコープで宣言するか、usingディレクティブ(3.4.3.2)のためにグローバルスコープで宣言が表示される名前にする必要があります。::を使用すると、識別子が非表示になっている場合でもグローバル名を参照できます(3.3.7)。

ここで重要なのは、グローバル名前空間でusingディレクティブを使用すると、スコープ演算子を使用してこれらのシンボルにアクセスできるようになることです。

また、7.3.1.1 / 1によると、匿名の名前空間は次のようになります。

namespace *unique* { /* empty body */ }
using namespace *unique*;
namespace *unique* { namespace-body }

したがって、これら2つのセクションの間で、スタンドアロン関数はグローバル名前空間でアクセスできる必要があります。

于 2011-03-31T18:05:39.253 に答える
7

アカデミックロボットが指摘するように、Visual C++ は間違っています。回避策として、名前のない空の名前空間ブロックを追加すると問題が解決するはずです (テストする Visual C++ 2008 はありませんが、これは Visual C++ 2010 で機能します)。

// empty unnamed namespace to placate compiler
namespace { }

namespace {
    void f() { }
    struct A {
        void f() { ::f(); }
    };
}

この問題を Visual C++ チームに報告しました。

于 2011-03-31T18:36:37.737 に答える