2016-03-05 19 views
8

Hãy xem xét các đoạn sau:tra cứu tên phụ thuộc vào chức năng template: kêu vang từ chối, gcc chấp nhận

struct X { }; 

namespace foo { 
    template <class T> 
    void bar() { T{} < T{}; } 

    void operator<(const X&, const X&) {} 
} 

int main() { 
    foo::bar<X>(); 
} 

kêu vang từ chối mã này, gcc chấp nhận nó. Đây có phải là lỗi gcc hay là lỗi này?

+0

Tôi không thấy đó là lỗi vì loại 'T' có thể tham chiếu đến bất kỳ loại nào. Nếu kiểu đó 'T' không quá tải hoặc hỗ trợ toán tử' <'thì hàm' bar' sẽ thất bại. Vì bạn đã quá tải toán tử '<' nên tất cả đều tốt. Tôi đoán nó tất cả đi xuống để làm thế nào trình biên dịch đọc mã, nhưng ngữ nghĩa khôn ngoan nó không phải là dễ bị lỗi. – Poriferous

+0

@ Poriferous Điều đó không có ý nghĩa gì cả. Câu hỏi đặt ra là về hành vi đúng của 'bar()' là cho các kiểu 'T' không có' toán tử <'. Hành vi đúng là: "có, nó tìm' bar :: operator <'" (trong trường hợp này, clang có lỗi) hoặc "mã bị lỗi" (trong trường hợp này, gcc có lỗi). – Barry

+0

Điều đó không có ý nghĩa bởi vì 'bar' là một hàm và không có toán tử' thành viên <'. Vì bạn đã định nghĩa 'toán tử <' cho struct 'X', tôi thực sự không thấy vấn đề là gì ở đây. Ngay cả khi quá tải của toán tử được nhúng trong cấu trúc 'X' thì mã vẫn phải biên dịch chính xác. Để công bằng, đó là tiếng kêu có lỗi kể từ khi nó xuất hiện để giả định một loại là gì. Tôi có nghĩa là, bạn đã thử thay thế 'foo :: thanh ()' với một cái gì đó như 'foo :: thanh ()' và xem nếu clang từ chối mã đó quá? – Poriferous

Trả lời

5

GCC sai Clang là chính xác. Thực tế là GCC nuốt mã không hợp lệ như mã mà bạn đã cho thấy cũng được đề cập trong trang tương thích của CLANG here.

Tên không đủ tiêu chuẩn được tra cứu theo các cách sau.

  1. Trình biên dịch tiến hành tra cứu không đủ tiêu chuẩn trong phạm vi tên được viết. Đối với mẫu, điều này có nghĩa là tra cứu được thực hiện tại điểm mà mẫu được xác định, không phải nơi mẫu được khởi tạo.operator< chưa được khai báo vào thời điểm này, tra cứu không đủ tiêu chuẩn sẽ không tìm thấy.
  2. Nếu tên được gọi là hàm, thì trình biên dịch cũng thực hiện tra cứu phụ thuộc đối số (ADL). (Đôi khi tra cứu không đủ tiêu chuẩn có thể ngăn chặn ADL; xem [basic.lookup.argdep] đoạn 3 để biết thêm thông tin.) Trong ADL, trình biên dịch xem xét các kiểu của tất cả các đối số cho cuộc gọi. Khi nó tìm thấy một loại lớp, nó tìm kiếm tên trong không gian tên của lớp đó; kết quả là tất cả các khai báo nó tìm thấy trong các không gian tên đó, cộng với các khai báo từ tra cứu không đủ tiêu chuẩn. Tuy nhiên, trình biên dịch không làm ADL cho đến khi nó biết tất cả các loại đối số.
6

Tôi tin rằng đây là lỗi gcc, được nộp là 70099. Từ [temp.dep.res]:

Trong việc giải quyết các tên thuộc, tên từ các nguồn sau đây được coi là:
(1.1) - Khai báo rằng có thể nhìn thấy tại thời điểm định nghĩa của mẫu.
(1.2) - Tuyên bố từ các không gian tên được liên kết với các loại đối số hàm cả từ bối cảnh instantiation (14.6.4.1) và từ ngữ cảnh định nghĩa.

foo::operator<() không nhìn thấy được tại thời điểm định nghĩa của mẫu, và không phải là trong một không gian tên liên quan đến từ các đối số chức năng (X 's liên quan đến không gian tên chỉ là không gian tên toàn cầu ::). Vì vậy, tôi nghĩ rằng gcc là sai để tìm foo::operator< và kêu vang là chính xác để từ chối mã.

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