2011-10-18 4 views
11
class extern "C"関数を使って classの友達を作ろうとすると、このコードは動作します:

extern "C"関数との友情は::を修飾する必要があるようです

#include <iostream> 

extern "C" { 
    void foo(); 
} 

namespace { 
    struct bar { 
    // without :: this refuses to compile 
    friend void ::foo(); 
    bar() : v(666) {} 
    private: 
    int v; 
    } inst; 
} 

int main() { 
    foo(); 
} 

extern "C" { 
    void foo() { 
    std::cout << inst.v << std::endl; 
    } 
} 

g ++ 4.6.1と4.4.4では、::friend void ::foo();に明示的に書く必要があります。友情はうまくいかない。この::extern "C"でも必要です。

  1. これはコンパイラのバグですか?私はその行動を期待していませんでした。
  2. これはバグではない場合、なぜこれが必要ですが、それがextern "C"で、それがなくてもかまいません。これを必要とする名前検索ルールの変更はどうでしょうか?

私は困惑しています。おそらく、私が見つけることができないいくつかのルールがあります。

+0

(http://codepad.org/Hw7JC8Ky )[ここ](http://codepad.org/9qVdlrhC)はテストケースです。 –

+0

これはバグですか?なぜなら、 'extern" C "'と匿名 'namespace'の組み合わせが' :: 'を必要とするが、どちらかを削除すると不要になる理由を説明するルックアップルールでは何も見つかりません。確かに名前検索の細部の詳細についての私の知識は曖昧であり、これは検索に基づいていました。 – Flexo

+0

@ TomalakGeret'kal - 匿名のものではなく、 'extern" C "' + 'namespace'で失敗します。 – Flexo

答えて

10

[n3290: 7.3.1.2/3]: Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) 95) this implies that the name of the class or function is unqualified. until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. [..]

最も内側の名前空間は、匿名の一つであり、そしてあなたは、関数名を修飾するので、the name is not foundませんでした。

名前空間need not be anonymousのいずれか。

問題のextern "C"the following also fails for the same reasonとして、赤ニシンであることに注意してください:[。ない場合、匿名の名前空間を持たない]

void foo(); 

namespace { 
struct T { 
    friend void foo(); 

    private: void bar() { cout << "!"; } 
} t; 
} 

void foo() { t.bar(); } 

int main() { 
    foo(); 
} 

/* 
In function 'void foo()': 
Line 7: error: 'void<unnamed>::T::bar()' is private 
compilation terminated due to -Wfatal-errors. 
*/ 

[alternative testcase, adapted from your original code]

+1

(_Why_については、誰もが知っている) –

関連する問題