11

私はこのコードを持っています:

#include <iostream>
#include <functional>

struct A
{
    int operator()(int i) const {
        std::cout << "F: " << i << std::endl;
        return i + 1;
    }
};

int main()
{
    A a;
    std::tr1::function<int(int)> f = std::tr1::ref(a);
    std::cout << f(6) << std::endl;
}

目的は、無駄なコピーコストラクタ呼び出しを回避する方法で、reference_wrapperによってファンクタオブジェクトを渡すことです。私は次の出力を期待しています:

F: 6
7

これは、GCC> = 4.4.0、Visual Studio 2008、およびstd::tr1名前空間をboostに置き換えることでboostで正しく機能します。ExpressBeta2とリリース候補の両方の新しいVisualStudio2010では機能しません。

この新しいC++機能はvs2010でバグがありますか?または、コードに間違いや誤用がありますか?

4

2 に答える 2

11

理由が分かった気がします。これは、TR13.4/2が について述べてresult_of<T(A1, A2, ..., AN)>::typeいることであり、 の戻り値の型の決定に使用されreference_wrapper<T>::operator()ます。

実装は、指定された型の式 f(t1, t2, ..., tN) の正確な型を生成する任意の手段を介して型メンバーを決定できます。[注: その意図は、実装が特別なコンパイラ フックの使用を許可されていることです — 末尾の注]

そして、パラグラフ3:

F が標準ライブラリで定義された関数オブジェクトではなく、実装が式 f(t1, t2, ..., tN) の型を判別できない場合、または式の形式が正しくない場合、実装は使用する必要があります。型メンバーを決定する次のプロセス:

  • F が cv 修飾された可能性のあるクラス型であり、メンバーが指定されていないresult_type場合、またはF が型でない場合typename F::result_type:
    • N=0 (引数なし) の場合、型は void です。
    • N>0 の場合、型はtypename F::template result<F(T1, T2,..., TN)>::type

エラー メッセージは、これらのフォールバックを試みた結果です。toに typedef を指定result_typeするintと、動作するはずです。C++0xでは、これが異なることに注意してください。result_typeを使用できるため、resultテンプレートに依存しませんdecltype

<functional>C++0x モードの MSVC10 で失敗した場合、バグのような匂いがします。しかし、おそらく他の誰かが何が起こっているのか知っています。その<tr1/functional>ヘッダーが. 私は typedef を使用します-そうすれば、ヘッダーが使用されているかヘッダーが使用されているかに関係なく、常に機能するはずです。decltype::result_typeresult_typetr1c++0x


boost::tr1また、はそのドキュメントで、関数呼び出し演算子をサポートしていないと述べていることに注意してください (ただし、 への暗黙的な変換をサポートしているだけT&です)。

于 2010-03-11T13:46:17.887 に答える
1

ここで同様の問題が発生します: C++ファンクターオブジェクトの不要なコピーを防止します

MSVC10 でコンパイルするには、関数オブジェクトを std::unary_function から派生させる必要がありました。

于 2010-03-11T14:12:22.077 に答える