2010-09-02 13 views
6

xem xét mã này:ADL và người bạn tiêm

template <int N> 
struct X 
{ 
friend void f(X *) {} 
}; 

int main() 
{ 
f((X<0> *)0); // Error? 
} 

trình biên dịch có vẻ nặng nề không đồng ý. (MSVC08/10 nói không, GCC < 4.5 nói có, nhưng 4,5 nói không, mặt trời 5.1 nói có, intel 11.1 nói có quá nhưng comeau nói không (cả hai đều là EDG)).

Theo "Mẫu C++ - Các hướng dẫn đầy đủ":

... người ta cho rằng một cuộc gọi liên quan đến một tra cứu cho bạn bè trong lớp liên quan thực sự làm cho lớp được khởi tạo .. Mặc dù điều này đã được dự định rõ ràng bởi những người đã viết tiêu chuẩn C++, nó không phải là được nêu rõ trong tiêu chuẩn.

Tôi không thể tìm thấy phần có liên quan trong tiêu chuẩn. Bất kỳ tài liệu tham khảo?

Hãy xem xét sự thay đổi này:

template <int N> 
struct X 
{ 
template <int M> 
friend void f(X<M> *) {} 
}; 

template <> 
struct X<0> 
{ 
}; 

int main() 
{ 
X<1>(); 
f((X<0> *)0); // Error? 
} 

Vấn đề mấu chốt ở đây là thời tiết các chức năng hữu hiệu đối tiêm bởi X<1> nên được hiển thị trong ADL cho X<0>? Chúng có liên quan không? Tất cả các trình biên dịch được đề cập ở trên đều chấp nhận mã này, ngoại trừ Comeau chỉ chấp nhận nó ở chế độ thư giãn. Không chắc chắn những gì tiêu chuẩn đã nói về điều này hoặc.

Bạn sẽ làm gì với điều đó?

Trả lời

4

Tiêu chuẩn nói tại 14.7.1/4

Một lớp mẫu chuyên môn được ngầm instantiated nếu kiểu lớp được sử dụng trong một bối cảnh đó đòi hỏi một loại đối tượng hoàn toàn xác định hoặc nếu tính đầy đủ của các loại lớp ảnh hưởng đến ngữ nghĩa của chương trình; đặc biệt, nếu một biểu thức có loại là một chuyên môn mẫu lớp có liên quan đến độ phân giải quá tải, chuyển đổi con trỏ, con trỏ đến chuyển đổi thành viên, chuyên môn mẫu lớp được khởi tạo ngầm (3.2);

Lưu ý rằng Vandervoorde làm một issue report here, và ủy ban tìm thấy

Các tiêu chuẩn đã quy định rằng điều này tạo ra một điểm instantiation.

Đối với trường hợp thứ hai của bạn - bạn cần xem xét các lớp và không gian tên liên quan của đối số f(X<0>*). Đây là, vì đây là một con trỏ đến một chuyên môn mẫu lớp (lưu ý rằng "template-id" bên dưới không hoàn toàn chính xác - C++ 0x đã sửa chữa để sử dụng cụm từ chính xác) và cũng là một con trỏ tới một lớp (phân tách khó hiểu này) cũng được sửa trong C++ 0x - nó liệt kê hai trường hợp này trong một dấu đầu dòng).

  • Nếu T là một mẫu-id, không gian tên có liên quan và các lớp học của nó là không gian tên trong đó mẫu là được xác định; [... rất nhiều tiếng ồn ...]

  • Nếu T là một loại lớp (bao gồm cả công đoàn), các lớp liên quan của nó là: chính lớp đó; lớp mà nó là thành viên, nếu có; và các lớp cơ bản trực tiếp và gián tiếp của nó. Các không gian tên liên quan của nó là các không gian tên trong đó các lớp liên kết của nó được định nghĩa.

Vì vậy, để tóm tắt, chúng tôi có các lớp học như đi kèm là X<0> và không gian tên có liên quan là không gian tên toàn cầu. Bây giờ các chức năng bạn có thể nhìn thấy là

  • Bất kỳ hàm friend namespace-phạm vi khai báo trong lớp học có liên quan được 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

Không có chức năng người bạn nào được khai báo trong X<0> để khai báo chức năng của bạn bè không hiển thị khi nhìn vào không gian tên chung. Lưu ý rằng X<0> là loại lớp hoàn toàn khác so với X<1>. Các instantiation ngầm của X<1> bạn làm không có ảnh hưởng đến cuộc gọi này - nó chỉ thêm một tên không nhìn thấy vào không gian tên toàn cầu đề cập đến một chức năng người bạn của lớp X<1>.

+0

Ví dụ đầu tiên có thể được biên dịch không? – jpalecek

+0

Cảm ơn :) Đây là nhiều hơn hoặc ít hơn những gì tôi nghi ngờ. Làm thế nào đến rất nhiều trình biên dịch nhận được rằng trường hợp thứ hai sai? Ngoài ra, tôi sẽ đánh giá cao nó nếu bạn có thể cung cấp tham chiếu vào tiêu chuẩn cho các dấu ngoặc kép khác nữa. – uj2

+0

@ uj2 tốt, ít nhất clang vẫn giữ được vẻ đẹp so với GCC. Nó chính xác từ chối trường hợp thứ hai. Đặc biệt GCC có khá nhiều vấn đề về tính tuân thủ mẫu nên điều này không làm tôi ngạc nhiên. Các trích dẫn khác bạn đang cố gắng tìm các đoạn Tiêu chuẩn là gì? –

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