2012-08-17 12 views
6

Mam następujący kod, który się nie kompiluje. To są dwie funkcje w klasie szablonu, że trwa argumentówMetoda szablonowa enable_if specjalizacja

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() { 
    // .... 
} 

chcę mieć specjalizację w sposobie zarejestrował się w zależności od rodzaju Ret jest.

Czy ktoś ma jakiś pomysł?

Odpowiedz

7

SFINAE nie działa w przypadku funkcji innych niż szablony (członek lub członek).

Jak wskazuje Kerrek SB, ich szablony funkcjonalne nie będące członkami będą działać. Lub, jak zaznacza Xeo, działa również szablonów funkcji członkowskich z domyślnym argumentem szablonu.

Działa to jednak tylko dlatego, że dwa warunki: std::enable_if to nienakładające się na siebie. Jeśli chcesz dodać inne przeciążenie dla int (powiedzmy), przekonasz się, że nie skaluje się tak ładnie. W zależności od tego, co chcesz zrobić, tag dyspozytorskich zazwyczaj skaluje lepiej niż SFINAE z wieloma alternatywami, które chcesz wysyłkę na:

#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

Można, jeśli jeden z przeciążeniami jest jedyną realną jeden w czasie rozmowy. :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo

+1

@Potatoswatter: Właściwie nie, to nie był żart. Zobacz link, możesz doskonale mieć funkcję z dokładnie tym samym podpisem, gdzie tylko typ powrotu decyduje, czy jest to wykonalne. : P Należy również użyć 'std :: is_void ()', cechy typu są wymagane do wyprowadzenia z 'std :: true_type' lub' std :: false_type'. – Xeo

+1

Btw, [możesz po prostu ustawić element członkowski jako szablon z domyślnym parametrem w C++ 11] (http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a). – Xeo

3

SFINAE działa tylko na szablonach. Kod można skompilować z małą modyfikacją:

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() { /*...*/ } 

Zastosowanie:

auto q = _on_dispatched<int>(); 

Można oczywiście nie wywnioskować typ zwracanej przez funkcję, ponieważ nie jest to wywnioskować. Jednak można zapakować ten szablon wewnątrz kolejny szablon:

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

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

'szablon ' dla funkcji członkowskich, zobacz mój komentarz dotyczący odpowiedzi rhalbersmy. – Xeo

+0

@Xeo: Masz na myśli, że uratowałoby nas to przed koniecznością napisania ''? Jasne, czemu nie :-) –

Powiązane problemy