6

検討:

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

decltype(f(args...))上記のテンプレートをポインターであるすべてのケースに部分的に特化する方法はありますか?

編集:テンプレート引数として取り、ヘルパークラスを特殊化する
テンプレートヘルパークラスで実行できると思います。decltype(f(args...))より良い解決策を知っている場合は、お知らせください。

4

2 に答える 2

3

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

テスト (ここではstd::is_pointer<Result>) を必要に応じて調整できます。

于 2012-06-16T13:06:19.250 に答える
1

ご覧のとおり、戻り型はテンプレート引数または引数の一部ではないため、オーバーロードしたり、特殊化したりすることはできません。ヘルパーに派遣するのが最善の選択肢です。

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

ただし、右辺値参照によって関数を取得するのは少し奇妙に思えます。また、元の例では転送を省略しています。

別の可能な解決策は、テンプレートのデフォルトの引数とその上でのオーバーロードである可能性があります。しかし、それは引数リストではうまく機能しません。

于 2012-06-16T12:46:01.527 に答える