2012-06-16 24 views
6

Rozważmy:Częściowa specjalizacja szablonu

template <typename Function, typename ...Args> 
auto wrapper(Function&& f, Args&&... args) -> decltype(f(args...)) { 
//... 
} 

Czy istnieje sposób, aby częściowo specjalizują powyższy szablon dla wszystkich przypadków, w których decltype(f(args...)) jest wskaźnik?

EDIT:
myślę, że można to zrobić z klasy pomocnika szablonu który odbywa decltype(f(args...)) jako szablonu argumentu, a specjalizujemy klasy pomocnika. Jeśli znasz lepsze rozwiązania, daj mi znać.

Odpowiedz

3

rozwiązanie oparte SFINAE:

#include <type_traits> 

template< 
    typename Functor 
    , typename... Args 
    , typename Result = decltype(std::declval<Functor&>()(std::declval<Args>()...)) 
    , typename std::enable_if< 
     std::is_pointer<Result>::value 
     , int 
    >::type = 0 
> 
Result wrapper(Functor&& functor, Args&&... args) 
{ /* ... */ } 

template< 
    typename Functor 
    , typename... Args 
    , typename Result = decltype(std::declval<Functor&>()(std::declval<Args>()...)) 
    , typename std::enable_if< 
     !std::is_pointer<Result>::value 
     , int 
    >::type = 0 
> 
Result wrapper(Functor&& functor, Args&&... args) 
{ /* ... */ } 

Można dostosować test (tutaj std::is_pointer<Result>) do swoich potrzeb.

1

Jak widać, typ zwracany nie jest argumentem szablonu ani częścią argumentów, więc nie można przeładować ani specjalizować. Wysyłanie na pomocnika to najlepsza opcja.

#include <type_traits> 

template<typename Func, typename... Args> 
void func_impl(Func&& f, Args&&... args, std::true_type) 
-> decltype(func_impl(std::forward<Args>(args)...)) 
{ } 

template<typename Func, typename... Args> 
void func_impl(Func&& f, Args&&... args, std::false_type) 
-> decltype(func_impl(std::forward<Args>(args)...)) 
{ } 

template<typename Func, typename... Args> 
auto func(Func&& f, Args&&... args) 
    -> decltype(func_impl(std::forward<Func>(f), std::forward<Args>(args)...)) 
{ return func_impl(std::forward<Func>(f), std::forward<Args>(args)..., 
        std::is_pointer<decltype(f(std::forward<Args>(args)...))>::type); } 

Wydaje mi się dziwne, bym wziął funkcję za pomocą wartości rvalue, a także pominąć przekazywanie w oryginalnym przykładzie.

Innym możliwym rozwiązaniem może być domyślny argument szablonu i jego przeciążenie. Ale to nie działałoby dobrze z listą argumentów.

Powiązane problemy