2017-04-19 13 views
8

Tôi đã dành một chút thời gian để hiểu tại sao mã của tôi không biên dịch và tôi đã nhận ra rằng trong C++ Tra cứu phụ thuộc đối tượng sử dụng tên tệp mẫu đối số để xác định phạm vi tra cứu tên.Lý do căn bản đằng sau ADL cho các đối số có loại là chuyên môn mẫu lớp

#include <string> 
#include <functional> 

namespace myns { 

    template<typename T> 
    struct X 
    {}; 

    template<typename T> 
    auto ref(T) -> void 
    {} 

} // namespace myns 

auto main() -> int 
{ 
    ref(myns::X<int>{}); 
    ref(myns::X<std::string>{}); // error: call to 'ref' is ambiguous 
} 

Vì vậy, các cựu gọi ref biên dịch, bởi vì đối với myns::X<int> chỉ myns::ref được coi là, trong khi sau này không biên dịch vì nó tìm thấy myns::ref() cũng như std::ref

Câu hỏi của tôi là thế nào điều này có thể hữu ích? Tại sao tôi cần điều này? Bạn có bất kỳ ý tưởng, ví dụ? Bây giờ tôi chỉ có thể thấy những hạn chế như trong ví dụ trên, nơi nó giới thiệu sự mơ hồ không cần thiết.

+0

Bạn có cần chức năng của mình để chấp nhận * bất kỳ * loại nào không? Nếu không 'auto ref (X ) -> void' sẽ phù hợp hơn' std :: ref' và được chọn bởi độ phân giải quá tải. –

+0

Thật không may, tôi có. – witosx

Trả lời

7

Giả sử bạn đặt tất cả mọi thứ vào không gian tên của riêng bạn, bao gồm lớp do người dùng xác định và một hàm lấy tham số std::vector. tức là

namespace myns { 

    struct X {}; 

    template<typename T> 
    auto my_func(const std::vector<T>&) -> void 
    {} 

} // namespace myns 

sau đó bạn có thể tận dụng thực tế là ADL cũng cân nhắc các loại được cung cấp như các đối số mẫu và chỉ cần viết:

my_func(std::vector<myns::X>{}); 

mặt khác:

my_func(std::vector<int>{});  // error, can't find my_func 
myns::my_func(std::vector<int>{}); // fine 

Quay lại câu hỏi ban đầu của bạn, bài học ở đây không sử dụng tên từ thư viện chuẩn , nó chỉ làm cho mã khó hiểu.

3

Trong một từ: sử dụng lại. Nó cho phép bạn sử dụng các thành phần hữu ích từ các thư viện khác, và vẫn áp dụng ADL.

Ví dụ:

namespace my_stuff { 
    class my_class { 
    // Something useful here 
    }; 

    void process(std::unique_ptr<my_class> item); 
} 

Bây giờ bạn có thể viết mã một cách tự nhiên, như bạn sẽ khi làm việc với các lớp học trực tiếp:

process(std::make_unique<my_class>()); 

Nếu nó không phải là trường hợp, bạn cần để đưa ra con trỏ thông minh của riêng bạn, trong không gian tên của riêng bạn, chỉ để tạo điều kiện cho các thành ngữ mã hóa tốt và ADL.

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