14

std::async次のように指定されていることがわかります。

template <class F, class... Args>                   // copied out of the standard
future<typename result_of<F(Args...)>::type>
async(F&& f, Args&&... args);

私はそれが次のように宣言されることを期待していました:

template <class F, class... Args>
auto async(F&& f, Args&&... args) ->
  future<decltype(forward<F>(f)(forward<Args>(args)...)>;

それは同等でしょうか、または の使用よりも の使用result_ofが好ましい方法はありdecltypeますか? result_of(式で動作する一方で、型で動作することを理解していdecltypeます。)

4

3 に答える 3

11

あなたのバージョンは、メンバーへのポインターなどでは機能しません。より近いが、まだ正確ではないバージョンは次のようになります。

template <class F, class... Args>
auto async(F&& f, Args&&... args)
-> future<decltype( ref(f)(forward<Args>(args)...) )>;

残ってstd::result_ofいる唯一の違いは、これがファンクターを左辺値として転送することです (あなたのバージョンも共有する問題です)。言い換えると、そのような呼び出し ( 経由std::reference_wrapper<F>) の結果は ですtypename std::result_of<F&(Args...)>::type

これは、標準ライブラリのいくつかのコンポーネント (いくつか例を挙げると、今見たものに加えて: std::threadstd::bindstd::function) がとらえどころのないINVOKE(f, a0, a1, ..., aN)と完全に同等ではない疑似式f(a0, a1, ... aN)はこれらのコンポーネントの 1 つであり、実際にはINVOKEstd::result_ofの結果の型を計算する役割を果たしているため、これが矛盾点です。

std::invoke型特性と連携するものはないためstd::result_of、後者は、たとえば、コードがそれらを呼び出すときに、関連する標準ライブラリ コンポーネントの戻り値の型を記述するのにのみ役立つと私は考えています。戻り値の型など、簡潔で自己文書化する方法が必要な場合 (decltypeあちこちに散らばるのと比較して、読みやすさの非常に価値のある目標)、独自のエイリアスを作成することをお勧めします。

template<typename F, typename... A>
using ResultOf = decltype( std::declval<F>()(std::declval<A>()...) );

ResultOf<F(A...)>(代わりにエイリアスを使用したい場合はResultOf<F, A...>、関数シグネチャのパターン マッチに少し機械が必要です。)

このエイリアスの追加の利点は、 とは異なり、SFINAE フレンドリーであることですstd::result_of。はい、それはもう 1 つの欠点です。(公平を期すために、これは次の標準のために修正されており、実装はすでにそれに追随しています。)

のおかげでメンバーへのポインターを適応させることができるので、そのようなトレイトを使用していたとしても、何も欠落することはありませんstd::mem_fn

于 2013-03-29T21:27:33.370 に答える
5

あなたの質問にはすでに違いがありましresult_ofdecltype

どちらも同じ機能を提供し (現在std::result_ofでも実装されています) 、式を作成するために必要な変数が既にあるため、例decltypeの違いはほとんどありません。

とはいえ、違いは、型しかない場合の構文糖衣に要約されます。検討:

typename std::result_of< F( A, B, C ) >::type

対。

decltype( std::declval<F>()( std::declval<A>(), std::declval<B>(), std::declval<C>() )

std::result_ofそして、それがそのような場合のオプションであることを覚えておいてください.

decltype使える場合と使えない場合があるので注意してくださいstd::result_of。を考慮してください。私の知る限り、同等のものを作成するdecltype( a + b )は見つかりません。Fstd::result_of< F( A, B ) >

于 2013-03-28T07:00:27.513 に答える
5

機能的な観点からはまったく違いはありません。ただし、このdecltypeバージョンではTrailing-return-typeが使用されています。これは、プログラミングの観点からの違いの 1 つです。

C++11 では、std::result_of絶対に必要というわけではありませんdecltype。代わりに、使用した方法のように使用できます。しかしstd::result_ofresult_of. メリットはあまり感じないけど。

個人的には、呼び出し可能なエンティティのみで動作するのに対し、decltypeより強力であらゆるエンティティで動作するため、使用することを好みます。result_ofを使えばdecltype、どこでも使えます。しかし ではresult_of、ときどき切り替える必要がdecltypeあります (つまり、エンティティが呼び出し可能でない場合)。すべての関数の戻り値の型で使用した github でこれを参照してください。decltype

于 2013-03-28T03:36:58.420 に答える