2011-10-18 16 views
11

試圖使class朋友與extern "C"功能,此代碼的工作:友誼爲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_,那麼誰知道frak知道) –