2015-06-05 27 views
26

Tôi đã sử dụng các phương pháp dựa trên SFINAE trong một thời gian dài, đặc biệt là để bật/tắt chuyên môn mẫu lớp cụ thể qua std::enable_if.SFINAE và chuyên môn mẫu từng phần

tôi là như vậy, một chút bối rối khi đọc bài báo mô tả các đề xuất void_t alias/phát hiện thành ngữ:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf

Phần 4 được dành cho việc thảo luận về tính hợp lệ của các thành ngữ, và đề cập đến một thảo luận trong đó hai bên tranh luận về khả năng ứng dụng của SFINAE trong các chuyên môn mẫu từng phần (với Richard Smith chỉ ra rằng tiêu chuẩn này thiếu từ ngữ về chủ đề này). Đến cuối của phần này, vấn đề CWG sau đây được đề cập

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2054

đây một lần nữa nó được nói rằng tiêu chuẩn không cho phép một cách rõ ràng ví dụ sao chép trong vấn đề này.

Tôi hơi bối rối bởi vì dường như với tôi, ví dụ, việc sử dụng enable_if trong chuyên môn từng phần đã được thực hành tiêu chuẩn trong một thời gian dài (xem tài liệu Boost, đề cập rõ ràng một phần chuyên môn).

Tôi có hiểu nhầm các điểm trong các tài liệu ở trên hoặc đây thực sự là vùng màu xám không?

+4

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

+0

@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

+2

Vâng, có lẽ không ai để ý. – Yakk

Trả lời

10

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 Tchar. 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.

+0

Đó là http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#697 –

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