7

xem xét như sau:Đối số tra cứu phụ thuộc cho bạn chức năng

namespace N { 
    struct A { }; 

    struct B { 
     B() { } 
     B(A const&) { } 
     friend void f(B const&) { } 
    }; 
} 

int main() { 
    f(N::B{}); // ok 
    f(N::A{}); // error 
} 

Trong trường hợp đầu tiên, trường hợp thành công - chúng tôi xem xét các không gian tên có liên quan của N::B và tìm N::f(B const&). Tuyệt quá.

Trường hợp thứ hai không thành công. Tại sao? Theo [namespace.memdef]:

Nếu một tuyên bố friend trong một lớp học không địa phương đầu tiên khai báo một lớp, chức năng, lớp mẫu hay hàm mẫu người bạn là một thành viên của không gian tên kèm theo trong cùng. [...] Nếu một hàm của bạn bè hoặc mẫu hàm được gọi, tên của nó có thể được tìm thấy bằng tra cứu tên xem xét các hàm từ các không gian tên và các lớp liên kết với các kiểu đối số hàm (3.4.2).

Các namespace liên quan của N::AN, trong đó f là thành viên, vì vậy tại sao nó không tìm thấy bằng cách tra cứu?

Trả lời

8

Đó là vì f không được khai báo trong lớp được liên kết. B là một lớp liên quan khi đối số là loại B, nhưng không phải khi đối số thuộc loại A.

tôi trích dẫn từ [basic.lookup.argdep]/4, tôi nhấn mạnh:

Khi xem xét một namespace liên quan, tra cứu là giống như tra cứu thực hiện khi namespace liên quan được sử dụng như một vòng loại (3.4.3.2) ngoại trừ:

- Bất kỳ chỉ thị sử dụng nào trong không gian tên được liên kết đều bị bỏ qua.

- Bất kỳ hàm friend namespace-phạm vi hoặc các hàm bạn bè mẫu khai báo trong lớp liên là có thể nhìn thấy trong không gian tên tương ứng của họ ngay cả khi họ không nhìn thấy được trong quá trình tra cứu thông thường (11,3).

- Tất cả các tên trừ các chức năng của (có thể quá tải) và các mẫu chức năng đều bị bỏ qua.

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