2014-06-24 25 views
7

Nhờ C++ 14, chúng tôi sẽ sớm có thể cắt giảm các loại trả về dài dòng; chẳng hạn như chung min ví dụ từ David Abrahams 2011 post:SFINAE với khấu trừ loại trả lại C++ 14

template <typename T, typename U> 
auto min(T x, U y) 
    -> typename std::remove_reference< decltype(x < y ? x : y) >::type 
{ return x < y ? x : y; } 

Dưới C++ 14 kiểu trả về có thể được bỏ qua, và min có thể được viết như sau:

template <typename T, typename U> 
auto min(T x, U y) 
{ return x < y ? x : y; } 

Đây là một ví dụ đơn giản Tuy nhiên, loại khấu trừ trả lại rất hữu ích cho mã chung, và có thể tránh được nhiều sự sao chép. Câu hỏi của tôi là, đối với các chức năng như thế này, làm cách nào để chúng tôi tích hợp các kỹ thuật SFINAE? Ví dụ: làm cách nào tôi có thể sử dụng std::enable_if để hạn chế chức năng min của chúng tôi để trả về các loại không thể tách rời?

Trả lời

12

Bạn không thể SFINAE chức năng bằng cách sử dụng loại trả lại nếu bạn đang sử dụng khấu trừ loại trả về. Điều này được đề cập trong số proposal

Vì loại trả về được suy ra bằng cách khởi tạo mẫu, nếu instantiation là hình thành, điều này gây ra lỗi thay vì lỗi thay thế.

Tuy nhiên, bạn có thể sử dụng thông số mẫu bổ sung, không được sử dụng để thực hiện SFINAE.

template <class T, class U> 
auto min1(T x, U y) 
{ return x < y ? x : y; } 

template <class T, class U, 
      class..., 
      class = std::enable_if_t<std::is_integral<T>::value && 
            std::is_integral<U>::value>> 
auto min2(T x, U y) 
{ 
    return x < y ? x : y; 
} 

struct foo {}; 

min1(foo{}, foo{}); // error - invalid operands to < 
min1(10, 20); 

min2(foo{}, foo{}); // error - no matching function min2 
min2(10, 20); 

Live demo

+2

+1 Bạn thậm chí có thể dùng lệnh 'std :: enable_if_t' mẫu helper. – 0x499602D2

+1

Chưa kể 'std :: is_integal_v'. – chris

+1

@ 0x499602D2 [Hình như] (http://coliru.stacked-crooked.com/a/8379c6d205210105) libstdC++ của gcc-4.9 có 'enable_if_it'. Tôi chắc chắn sẽ sử dụng nó thường xuyên hơn. Với gcc-4.8 Tôi không bao giờ sử dụng nó vì tôi không muốn thay đổi dòng lệnh của coliru quá nhiều giữa clang và gcc :) – Praetorian

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