2012-08-17 50 views
6

tôi có mã sau không biên dịch. Đây là hai chức năng trong một lớp mẫu mà sẽ đưa các đối sốPhương pháp mẫu enable_if chuyên môn

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // ... 
} 

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // .... 
} 

Tôi muốn có một chuyên môn hóa trong một phương pháp thành viên tùy thuộc vào loại Ret là.

Có ai đó có ý tưởng nào không?

Trả lời

7

SFINAE không hoạt động trên các chức năng không phải mẫu (thành viên hoặc không phải thành viên).

Khi Kerrek SB chỉ ra, làm cho chúng trở thành mẫu chức năng không phải thành viên sẽ hoạt động. Hoặc như Xeo chỉ ra, làm cho chúng thành viên các mẫu chức năng với một đối số mẫu mặc định cũng sẽ làm việc.

Tuy nhiên, điều này chỉ hoạt động vì hai điều kiện std::enable_ifkhông chồng chéo. Nếu bạn muốn thêm một tình trạng quá tải khác nhau cho int (nói), thì bạn sẽ thấy rằng nó không quy mô như độc đáo. Tùy thuộc vào những gì bạn muốn làm, thẻ dispatching nói chung quy mô tốt hơn so với SFINAE với nhiều lựa chọn thay thế mà bạn muốn để gửi về:

#include<type_traits> 

template<typename Ret> 
class Foo 
{ 
public: 
    void _on_dispatched() 
    { 
     // tag dispachting: create dummy of either std::false_type or std::true_type 
     // almost guaranteed to be optimized away by a decent compiler 
     helper_on_dispatched(std::is_void<Ret>()); 
    } 

private: 
    void helper_on_dispatched(std::false_type) 
    { 
     // do stuff for non-void 
    } 

    void helper_on_dispatched(std::true_type) 
    { 
     // do stuff for void 
    } 
}; 

int main() 
{ 
    Foo<void>()._on_dispatched(); 
    Foo<int>()._on_dispatched(); 
    return 0; 
} 
+1

Bạn có thể, nếu một trong những quá tải là một trong những khả thi duy nhất vào thời điểm cuộc gọi. :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo

+1

@Potatoswatter: Thật ra, không, đó không phải là trò đùa. Xem liên kết, bạn hoàn toàn có thể có một hàm với chính xác cùng một chữ ký trong đó chỉ có kiểu trả về quyết định nếu nó có khả thi. : P Ngoài ra, chỉ cần sử dụng 'std :: is_void ()', loại đặc điểm được yêu cầu để lấy được từ một trong hai 'std :: true_type' hoặc' std :: false_type'. – Xeo

+1

Btw, [bạn chỉ có thể làm cho thành viên hoạt động một mẫu với tham số mặc định trong C++ 11] (http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a). – Xeo

3

SFINAE chỉ hoạt động trên các mẫu. Mã của bạn có thể được thực hiện để biên dịch với một thay đổi nhỏ:

template <typename Ret> 
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

template <typename Ret> 
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

Cách sử dụng:

auto q = _on_dispatched<int>(); 

Bạn có thể dĩ nhiên không suy ra kiểu trả về của một hàm, vì nó không phải là deducible. Tuy nhiên, bạn có thể đóng gói mẫu này bên khác mẫu:

template <typename T> 
struct Foo 
{ 
    // insert templates here, maybe privately so 

    T bar() { return _on_dispatched<T>(); } 
}; 
+0

'mẫu ' cho các hàm thành viên, xem bình luận của tôi về câu trả lời của rhalbersma. – Xeo

+0

@Xeo: Ý anh là điều đó sẽ cứu chúng ta khỏi phải viết ' '? Chắc chắn, tại sao không :-) –

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