2011-10-18 21 views
11

Đang cố gắng để thực hiện một class kết bạn với một chức năng extern "C", mã này hoạt động:hệ hữu nghị với extern chức năng "C" dường như đòi hỏi :: để đủ điều kiện tên

#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; 
    } 
} 

Nhưng tôi đã rất ngạc nhiên khi thấy rằng với g ++ 4.6.1 và 4.4.4 Tôi phải viết rõ ràng :: trong friend void ::foo(); nếu không tình bạn không hoạt động. Tuy nhiên, chỉ cần :: khi đó là extern "C".

  1. Đây có phải là lỗi/lỗi trình biên dịch không? Tôi đã không mong đợi hành vi đó.
  2. Nếu nó không phải là lỗi tại sao điều này là bắt buộc, nhưng chỉ khi đó là extern "C" và không phải không có nó? Điều gì về các quy tắc tra cứu tên thay đổi mà làm cho điều này cần thiết?

Tôi bị chặn. Có lẽ một số quy tắc cho điều này mà tôi không thể tìm thấy.

+0

(http://codepad.org/Hw7JC8Ky) Và [ở đây] (http://codepad.org/9qVdlrhC) là testcase. –

+0

Hmm là một lỗi sau đó? Tôi không thể tìm thấy bất cứ điều gì trong các quy tắc tra cứu sẽ giải thích tại sao sự kết hợp của 'extern" C "' và nặc danh 'không gian tên' sẽ cần' :: 'nhưng loại bỏ hoặc làm cho nó không cần thiết. Phải thừa nhận rằng mặc dù kiến ​​thức của tôi về các chi tiết tốt hơn về tra cứu tên là mờ và điều này được dựa trên tìm kiếm. – Flexo

+0

@ TomalakGeret'kal - nó không thành công với bất kỳ 'extern" C "' + 'không gian tên', không chỉ là những ẩn danh. – Flexo

Trả lời

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. [..]

Không gian tên kèm theo bên trong là không xác định và bạn không đủ điều kiện tên hàm, do đó the name is not found.

Không gian tên need not be anonymous, một trong hai.

Lưu ý rằng extern "C" trong câu hỏi là một cá trích đỏ, như the following also fails for the same reason: [. Không phải là trường hợp mà không có không gian tên vô danh]

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

(Đối với _Why_, ai là người biết frak) –

Các vấn đề liên quan