Tôi muốn cho rằng Tiêu chuẩn không hỗ trợ SFINAE trong chuyên môn từng phần, do lỗi từ ngữ. Hãy bắt đầu với [temp.class.spec.match]:
Một đặc tả từng phần phù hợp với một danh sách đối số mẫu thực tế đưa ra nếu các đối số mẫu của chuyên môn hóa một phần có thể được suy luận từ danh sách mẫu tranh luận thực tế (14.8.2).
Và, từ [temp.deduct], mệnh đề SFINAE:
Nếu một kết quả thay thế trong một kiểu không hợp lệ hoặc biểu hiện, loại trừ thất bại. Loại hoặc biểu thức không hợp lệ là loại hoặc hình thức không đúng, với yêu cầu chẩn đoán, nếu được viết bằng các đối số được thay thế. [Lưu ý: Nếu không cần chẩn đoán, chương trình vẫn bị hỏng. Kiểm tra truy cập được thực hiện như một phần của quá trình thay thế . —thêm ghi chú] Chỉ các loại và biểu thức không hợp lệ trong bối cảnh ngay lập tức của loại chức năng và các kiểu tham số mẫu của nó có thể dẫn đến lỗi khấu trừ.
Ví dụ được sửa đổi một chút & dagger; từ CWG là:
template <class T, class U> struct X {
typedef char member;
};
template<class T> struct X<T,
typename enable_if<(sizeof(T)>sizeof(
float)), float>::type>
{
typedef long long member;
};
int main() {
cout << sizeof(X<char, float>::member);
}
Tên tra cứu trên X
tìm tiểu học, với T == char, U == float
. Chúng tôi xem xét chuyên môn một phần và xem liệu "đối sánh" có nghĩa là các đối số mẫu "có thể được suy luận không" - nghĩa là:
+-------------+--------+-------------------------------------------------+
| | arg1 arg2 |
+-------------+--------+-------------------------------------------------+
| deduce T in | T | enable_if_t<(sizeof(T) > sizeof(float), float> |
| from | char | float |
+-------------+--------+-------------------------------------------------+
Quy tắc khấu trừ mẫu thông thường được áp dụng."Đối số" thứ hai là ngữ cảnh không thể suy luận, vì vậy chúng tôi suy ra T
là char
. sizeof(char) > sizeof(float)
, là sai, và enable_if_t<false, float>
là một loại không hợp lệ, vì vậy loại trừ nên thất bại ... nhưng, thất bại khấu trừ chỉ có thể xảy ra
trong bối cảnh trước mắt của loại chức năng và các loại tham số mẫu của nó
và chúng tôi không xử lý các loại thông số mẫu chức năng hoặc loại hàm, chúng tôi đang xử lý các loại tham số mẫu lớp. Một lớp không phải là một hàm, do đó việc loại bỏ SFINAE không nên áp dụng nếu chúng ta lấy mọi thứ theo nghĩa đen - và ví dụ CWG đã sửa đổi sẽ dẫn đến một lỗi nghiêm trọng.
Tuy nhiên, tinh thần của quy tắc có vẻ là hơn dọc theo dòng:
loại Chỉ không hợp lệ và biểu thức trong bối cảnh trước mắt của các quá trình trích có thể dẫn đến một thất bại khấu trừ.
Tôi không biết lý do sẽ loại trừ cụ thể loại khấu trừ đặc biệt một phần của lớp học. Hơn nữa, đặt hàng một phần các chuyên môn từng phần của mẫu lớp cũng giống như các hàm. Từ [temp.class.order]:
Đối với hai lớp mẫu chuyên ngành phần, đầu tiên là chuyên biệt hơn so với thứ hai nếu, do sau viết lại để hai mẫu chức năng, [...]
Chuẩn do đó đã là trong phần tiếp theo thể hiện tính hai mặt giữa các mẫu chuyên môn từng phần và mẫu chức năng. Thực tế là điều này chỉ áp dụng cho việc đặt hàng chuyên môn hóa một phần, và không thay thế thất bại trong khi khấu trừ đối số chuyên môn hóa một phần, tấn công tôi như là một khiếm khuyết.
& dagger; Bản thân ví dụ là X<double, float>
. Nhưng điều này thực sự không chứng minh hoặc yêu cầu SFINAE, vì sẽ không có sự thất bại thay thế ở bất cứ đâu.
Nó có vẻ giống như một đối số phong nha, cả hai tiêu chuẩn không chỉ định nó, và mỗi thực hiện xử lý nó như bạn muốn, và rằng nó gần như chắc chắn sẽ được giải quyết theo cách phù hợp với hiện trạng? – Yakk
@Yakk nhưng sau đó tôi hơi ngạc nhiên khi thấy nó được quảng cáo như một cách di động để làm những việc trong vòng kết nối như Tăng cường và stackoverflow. Đây là một kỹ thuật, trong các hình thức trước đó, ngày tháng với C++ 03, có vẻ như nó sẽ không được tiêu chuẩn hóa trong C++ 11/C++ 14. – bluescarni
Vâng, có lẽ không ai để ý. – Yakk