4

他の関数をラップするが、ラップされた呼び出しの後に何かを行う関数を考えてみましょう。

template< typename ftor, typename ... args >
typename std::result_of< ftor( args ... ) >::type
call_and_report( ftor && f, args && ... a ) {
    auto && ret{ f( std::forward< args >( a ) ... ) };
    std::cout << "Done!\n";
    return std::forward< typename std::result_of< ftor( args ... ) >::type >
                       ( ret );
}

これを拡張して、返す関数をラップする方法はvoid? 別の専門分野を追加するのは簡単ですが、慣用的な別の方法を探しています。

一般的な考え方は、値がある場合とない場合があるということです。コンパイル時のようなものoptionalです。

4

3 に答える 3

4

関数の実行で戻ることは合法です。

template <typename F, typename ... Args>
auto call_and_report(F && f, Args && ... a) 
    -> decltype(f(std::forward<Args>(a)...))
{
    return f(std::forward<Args>(a)...);
}

呼び出し後に何かを行うには、オブジェクトのデストラクタで行うことができます。

template <typename F, typename ... Args>
auto call_and_report(F && f, Args && ... a) 
    -> decltype(f(std::forward<Args>(a)...))
{
    struct execute { ~execute() { std::cout << "Done!" << '\n'; } } execute;
    return f(std::forward<Args>(a)...);
}
于 2013-09-16T08:26:34.667 に答える
1

最も簡単な方法は、ローカル オブジェクトのデストラクタで追加のコードを実行することです。そうすることで、結果を直接渡すこともできます。これにより、左辺値以外の戻り値で必要なコピー/移動を省略できます。

template <typename F, typename... Args>
...
call_and_forward(F&& f, Args&&... args) {
    struct report {
        ~report() { std::cout << "done\n"; }
    } reporter;
    return f(std::forward<Args>(args)...);
}
于 2013-09-16T08:38:08.460 に答える
0

これは、問題を少なくとも再利用できるような形で専用のラッパーに移す試みです。

正確性がわからないため、一度もコンパイルを試みていません。少なくとも、 はstatic_cast値で返すときに不要なコピーを作成します。

私は好奇心からこれを行っているだけで、実際にはこの問題の解決策は必要ありませんが、かなり面倒に見えます。

template< typename ftor, typename ... args >
typename std::enable_if< ! std::is_void< typename std::result_of< ftor( args ... ) >::type >::value,
    typename std::result_of< ftor( args ... ) >::type >::type
call_or_wrap_void( ftor && f, args && ... a )
    { return std::forward< ftor >( f ) ( std::forward< args >( a ) ... ); }

struct void_wrapper {};

template< typename ftor, typename ... args >
typename std::enable_if< std::is_void< typename std::result_of< ftor( args ... ) >::type >::value,
    void_wrapper >::type
call_or_wrap_void( ftor && f, args && ... a ) {
    std::forward< ftor >( f ) ( std::forward< args >( a ) ... );
    return {};
}

template< typename ftor, typename ... args >
typename std::result_of< ftor( args ... ) >::type
call_and_report( ftor && f, args && ... a ) {
    auto && ret{ call_or_wrap_void( std::forward< ftor >( f ), std::forward< args >( a ) ... ) };
    std::cout << "Done!\n";
    return static_cast< typename std::result_of< ftor( args ... ) >::type >
                      ( std::move( ret ) );
}
于 2013-09-16T09:02:53.423 に答える