Dưới đây là một ví dụ nhỏ gọn của một nghị quyết tình trạng quá tải rất lạ từ một mẫu bối cảnh:C++ độ phân giải mẫu quá tải gọi từ ứng cử viên chọn mẫu chức năng tuyên bố sau khi mẫu instantiation
#include <iostream>
// Types //
struct I { int v; };
template <class T>
struct D { T t; };
// Functions //
// Overload 1
template <class T>
I f(T) { return {1}; }
// Template indirection that calls f(T)
template <class T>
I g(D<T>) { return f(T{}); }
// Non template indirection that calls f(T)
I h(D<I>) { return f(I{}); }
int main() {
std::cout
<< f(I{}).v // f(I{}) overload called directly
<< "\n" // => overload 1 called
<< h(D<I>{}).v // f(I{}) called though non-template
<< "\n" // => overload 1 called
<< g(D<I>{}).v // f(I{}) called though template
<< "\n"; // => overload 2 actually called ???
}
// Overload 2
// Should not be reachable as declared after all f(...) calls.
// If was a candidate, would be chosen over 1.
I f(I) { return {2}; }
này dường như có liên quan đến ADL vì nếu I
được đặt trong một không gian tên "quá tải 1" luôn được gọi.
Tôi biết rằng ADL được thực hiện như thể cuộc gọi được thực hiện từ điểm khởi tạo mẫu (main
).
Đối với tên phụ thuộc được sử dụng trong định nghĩa mẫu, tra cứu được hoãn cho đến khi đối số mẫu được biết, tại thời điểm đó ADL kiểm tra khai báo hàm với liên kết bên ngoài (cho đến C++ 11). ngữ cảnh định nghĩa cũng như trong bối cảnh instantiation mẫu, trong khi tra cứu không phải ADL chỉ kiểm tra các khai báo hàm với liên kết bên ngoài (cho đến C++ 11) được hiển thị từ ngữ cảnh định nghĩa mẫu. http://en.cppreference.com/w/cpp/language/unqualified_lookup#Template_definition
Nhưng tại đây "Quá tải 2" được khai báo SAU main
! main
là điểm instanciation của g
và f
, tôi giả định chỉ chức năng được khai báo trướcmain
sẽ là ứng cử viên quá tải.
Lưu ý rằng hành vi này có liên quan đến g
là mẫu dưới dạng hàm mẫu không tương thích của h
(g
) gọi là "Quá tải 1".
Làm cách nào để "quá tải 2" - được tuyên bố sau main
- bao giờ được gọi?
Hành vi này đã được sao chép bằng tiếng kêu + (3.8.1) và g ++ (6.2.1).
Điều đó bổ sung thêm một hòn đá khác chống lại việc thêm quá tải vào không gian tên của thư viện. Việc bổ sung này có thể dẫn đến hành vi không xác định nếu quá tải này có thể được chọn trong mã thư viện. Biết quy tắc, không hợp lý. –