2011-01-05 24 views
6

Lý do cơ bản của tra cứu Koenig là gì?Lý do để tra cứu Koenig

Không thể tránh suy nghĩ về điều gì đó khiến mã của bạn khó đọc hơn và nhiều hơn nữa instable.

Không thể xác định tra cứu Koenig để nó chỉ hoạt động cho các trường hợp cụ thể (ví dụ: nhà khai thác không phải thành viên) hoặc khi được yêu cầu một cách rõ ràng?

+0

Không bao giờ nghĩ về điều đó. Vì vậy, ngay cả tôi cũng muốn biết điều đó. Câu hỏi hay! – Nawaz

Trả lời

5

Động lực ban đầu, IIRC, là để có thể viết

std::cout << 42; 

mà không cần phải hội đủ điều kiện std::operator<<(std::ostream&, int) explicitely.

Nếu bạn muốn tắt tìm kiếm phụ thuộc đối số, bạn có thể đủ điều kiện rõ ràng tên hàm, ví dụ: sử dụng std::swap thay vì swap để ngăn không cho swap được tra cứu trong bất kỳ không gian tên nào mà các đối số của nó sẽ hoạt động. ADL cũng có thể được sử dụng với SFINAE để kiểm tra tại thời gian biên dịch cho dù một số chức năng được xác định cho một loại cụ thể (tôi sẽ cho phép bạn làm việc này như là một bài tập, có ít nhất một câu hỏi về điều này trên Stackoverflow).

+0

Tôi nghĩ SFINAE đã được hình thành sau khi ADL được giới thiệu. Quan điểm của tôi là tôi muốn bị buộc phải nói rõ không gian tên nào để sử dụng (hoặc nói rõ ràng để áp dụng ADL). ... Tôi đã giải thích một đoạn mã tôi đã viết cho một người bạn của tôi, những người không nói chuyện với C++; sau khi tôi dành mười phút nói về các không gian tên, anh ấy hỏi tôi tại sao, trong đoạn mã của tôi, tôi có thể sử dụng một hàm từ một không gian tên khác mà không làm cho nó rõ ràng.Tôi nghe khá giống "oh, vâng, bởi vì C++ cũng có quy tắc khác ..." – peoro

+0

@peoro: C++ có rất nhiều quy tắc lạ, và điều này sẽ tệ hơn với C++ 0x. Tuy nhiên, tôi nghĩ rằng tốt nhất nên tránh ADL bằng cách gọi các hàm thành viên với 'this->' và sử dụng các bằng cấp rõ ràng bất cứ khi nào nó có ý nghĩa. Hầu hết thời gian, bạn không cần điều này (trừ các cuộc gọi hàm thành viên). Và có những lúc ADL là tuyệt vời. –

+0

@ Alexandre C .: Vâng, tôi biết nó có thể tránh được theo cách đó, nhưng điều đó không trả lời tại sao ADL tồn tại. Tôi nghĩ (đây là ý kiến ​​cá nhân của tôi, vâng) nó sẽ đơn giản và sạch hơn nếu không có nó, và bị buộc phải _avoid_ nó. Trong trường hợp nào thì nó tuyệt vời? Tại thời điểm này tôi thấy nó giống như một quy tắc kỳ lạ của C++ có thể dễ dàng tránh được trong một ngôn ngữ với một cú pháp tốt. – peoro

3

Trường hợp sử dụng mạnh nhất cho ADL là dành cho các trường hợp như thế này.

namespace A 
{ 
    struct S {}; 
    S operator+(const S&, const S&); 
} 

namespace B 
{ 
    A::S test() 
    { 
     A::S a, b; 
     return a + b; 
    } 
} 

Nó cũng hữu ích cho việc lựa chọn đúng swap hàm trong mã chung vì vậy không nên chỉ áp dụng cho operator chức năng. Nó đã là một phần khá phức tạp của tiêu chuẩn, làm cho các quy tắc ngăn cản nó hoạt động trong một số trường hợp sẽ thêm độ phức tạp hơn nữa, điều gì sẽ là lợi ích?

Tôi không thể nghĩ ra bất kỳ cách gọn gàng nào để yêu cầu rõ ràng rằng sẽ tiết kiệm hơn một cách đáng kể so với việc gọi một hàm trong một không gian tên khác một cách trực tiếp và trong mọi trường hợp.

Chúng tôi đang nghĩ đến điều gì đó như: return [[ use_adl ]] (a + b);return A::operator+(a, b);?

+0

Thực ra tôi đã suy nghĩ để thêm một số loại từ khóa bên trong hàm sử dụng tìm kiếm koenig: 'void f (const T & a) {namespaceof (T) :: ...; } '... – peoro

+2

@peroro:' namespaceof (T) 'rất nhiều âm thanh như bạn đang chỉ định một không gian tên cụ thể để tìm kiếm; trong trường hợp đó bạn không cần ADL chút nào. Bạn cũng có thể sử dụng id đủ điều kiện. –

+0

@Charles Bailey: Vâng nhưng câu hỏi của tôi vẫn còn đó. Nó sẽ không đơn giản hơn (đối với các trình biên dịch và chuẩn) và sạch hơn (đối với các lập trình viên và chuẩn) để có một toán tử như 'namespaceof' thay vì ADL, và buộc phải sử dụng không gian tên một cách rõ ràng? – peoro