2012-06-16 23 views
6

Considere:especialización parcial de una plantilla

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

¿Hay una manera de especializarse en parte la plantilla anterior para todos los casos en los que decltype(f(args...)) es un puntero?

EDITAR:
creo que se puede hacer con una plantilla de clase de ayuda que toma como argumento decltype(f(args...)) plantilla, y se especializan la clase de ayuda. Si conoces mejores soluciones, házmelo saber.

Respuesta

3

solución basada en un 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) 
{ /* ... */ } 

Puede adaptar la prueba (en este caso, std::is_pointer<Result>) a sus necesidades.

1

Como ve, el tipo de devolución no es un argumento de plantilla o parte de los argumentos, por lo que no puede sobrecargar ni especializarse. Despachar a un ayudante es su mejor opción.

#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); } 

parece un poco extraño para mí tomar la función por referencia rvalue sin embargo y también omitir el envío en su original ejemplo.

Otra posible solución podría ser un argumento predeterminado de plantilla y una sobrecarga en eso. Pero eso no funcionaría bien con la lista de argumentos.

Cuestiones relacionadas