Reputation: 9359
Consider:
template <typename Function, typename ...Args>
auto wrapper(Function&& f, Args&&... args) -> decltype(f(args...)) {
//...
}
Is there a way to partially specialize the above template for all the cases where decltype(f(args...))
is a pointer?
EDIT:
I think it can be done with an template helper class which takes decltype(f(args...))
as template argument, and specialize the helper class. If you know better solutions let me know.
Upvotes: 6
Views: 213
Reputation: 35439
An SFINAE-based solution:
#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)
{ /* ... */ }
You can adapt the test (here, std::is_pointer<Result>
) to your needs.
Upvotes: 3
Reputation: 59811
As you see the return type is not a template argument or part of the arguments, so you cannot overload nor specialize. Dispatching on a helper is your best option.
#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); }
It seems a little odd to me to take the function by rvalue reference though and you also omit the forwarding in your original example.
Another possible solution could be a template default argument and overload on that. But that wouldn't work well with the argument list.
Upvotes: 1