ご覧のとおり、戻り型はテンプレート引数または引数の一部ではないため、オーバーロードしたり、特殊化したりすることはできません。ヘルパーに派遣するのが最善の選択肢です。
#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); }
ただし、右辺値参照によって関数を取得するのは少し奇妙に思えます。また、元の例では転送を省略しています。
別の可能な解決策は、テンプレートのデフォルトの引数とその上でのオーバーロードである可能性があります。しかし、それは引数リストではうまく機能しません。