あなたのバージョンは、メンバーへのポインターなどでは機能しません。より近いが、まだ正確ではないバージョンは次のようになります。
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::thread
、std::bind
、std::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
。