105

std::result_ofC++0x での必要性を理解するのに苦労しています。私が正しく理解していればresult_of、特定のタイプのパラメーターを持つ関数オブジェクトを呼び出す結果のタイプを取得するために使用されます。例えば:

template <typename F, typename Arg>
typename std::result_of<F(Arg)>::type
invoke(F f, Arg a)
{
    return f(a);
}

次のコードとの違いはよくわかりません。

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter
{
    return f(a);
}

また

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F
{
    return f(a);
}

これらの 2 つのソリューションで私が確認できる唯一の問題は、次のいずれかを行う必要があることです。

  • decltype に渡される式で使用するファンクタのインスタンスを用意します。
  • ファンクターの定義済みコンストラクターを知っている。

decltypeとの唯一の違いresult_ofは、最初のものには式が必要であるのに対し、2 番目のものには必要がないということであると考えるのは正しいでしょうか?

4

2 に答える 2

88

result_ofBoost で導入され、その後TR1に組み込まれ、最後に C++0x に組み込まれました。したがってresult_of、(適切なライブラリとの) 下位互換性があるという利点があります。

decltypeは C++0x のまったく新しいものであり、関数の戻り値の型だけに限定されるものではなく、言語機能です。


とにかく、gcc 4.5 では、次result_ofのように実装されていますdecltype

  template<typename _Signature>
    class result_of;

  template<typename _Functor, typename... _ArgTypes>
    struct result_of<_Functor(_ArgTypes...)>
    {
      typedef
        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
        type;
    };
于 2010-04-22T09:54:40.017 に答える
12

関数呼び出しのようなものではない型が必要な場合は、std::result_of当てはまりません。decltype()任意の式の型を与えることができます。

関数呼び出しの戻り値の型を決定するさまざまな方法 ( と の間std::result_of_t<F(Args...)>)だけに制限するdecltype(std::declval<F>()(std::declval<Args>()...)と、違いがあります。

std::result_of<F(Args...)と定義されている:

INVOKE (declval<Fn>(), declval<ArgTypes>()...)未評価のオペランドとして扱われるときに式 が適切に形成されている場合 (第 5 節)、メンバー typedef 型は型に名前を付けるものとしdecltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...)); ます。そうでない場合、メンバー型は存在しません。

result_of<F(Args..)>::typeとの違いはdecltype(std::declval<F>()(std::declval<Args>()...)それだけINVOKEです。declval/を直接使用decltypeすると、入力がかなり長くなるだけでなく、F直接呼び出し可能な場合 (関数オブジェクト型または関数または関数ポインター) にのみ有効です。result_ofさらに、メンバー関数へのポインターとメンバー データへのポインターをサポートします。

最初は、declval/を使用decltypeすると SFINAE に適した式が保証されていましstd::result_ofたが、推論の失敗ではなくハード エラーが発生する可能性がありました。これは C++14 で修正されました: SFINAE 対応であることが要求されるようになりました (この論文std::result_ofのおかげです)。

したがって、準拠する C++14 コンパイラでstd::result_of_t<F(Args...)>は、厳密に優れています。より明確で、短く、正確ですFより多くのをサポートします。


つまり、メンバーへのポインターを許可したくないコンテキストで使用しているstd::result_of_t場合を除き、失敗したい場合でも成功します。

例外あり。メンバーへのポインターをサポートしていますが、無効なtype-idresult_ofをインスタンス化しようとすると機能しません。これらには、関数を返す関数、または抽象型を値で受け取る関数が含まれます。元。:

template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }

int answer() { return 42; }

call(answer); // nope

正しい使用法はresult_of_t<F&()>でしたが、それは で覚える必要のない詳細ですdecltype

于 2016-03-07T00:04:24.933 に答える