13

私はc++11の新機能を学んでいて、この問題に遭遇しました。for_eachの引数として、unique_ptrをラムダ内に移動してキャプチャしたいと思います。

設定:

std::array<int,4> arr = {1,3,5,6};
std::unique_ptr<int> p(new int);  (*p) = 3;

試行1-unique_ptrにはコピーコンストラクターがないため、機能しません。c ++ 0xは、passbymove構文を指定しません。

std::for_each(arr.begin(), arr.end(), [p](int& i) { i+=*p; });

試行2-bindを使用して、移動したpのコピーをint&を受け取る関数にバインドします。

std::for_each(arr.begin(), arr.end(),
     std::bind([](const unique_ptr<int>& p, int& i){
          i += (*p);
     }, std::move(p))
);

コンパイラはそれを文句を言う'result' : symbol is neither a class template nor a function template.

演習の主な目的は、後で使用するためにキャッシュされるラムダに可動変数がどのようにキャプチャされるかを理解することです。

4

2 に答える 2

20

更新:C++14以降のラムダで可動変数をキャプチャできます。

std::for_each(arr.begin(), arr.end(), [p=std::move(p)](int& i) { i+=*p; });

C ++ 11では、移動可能な変数を簡単な方法でラムダにキャプチャすることはできません。

ラムダはコピーまたは参照によってキャプチャします。したがって、移動専用変数をキャプチャするには、copying => move(などstd::auto_ptr)のオブジェクトでラップする必要があります。これは厄介なハックです。

あなたの例では、参照によってキャプチャすることができますが、これが単純化されたコードである場合、実際のコードでは期待どおりに機能しない可能性があります。

std::for_each(arr.begin(), arr.end(), [&p](int& i) { i+=*p; });

コピー移動のみのラッパーは次のとおりです。

template<typename T>
struct move_on_copy_wrapper
{
    mutable T value;

    move_on_copy_wrapper(T&& t):
        value(std::move(t))
    {}

    move_on_copy_wrapper(move_on_copy_wrapper const& other):
        value(std::move(other.value))
    {}

    move_on_copy_wrapper(move_on_copy_wrapper&& other):
        value(std::move(other.value))
    {}

    move_on_copy_wrapper& operator=(move_on_copy_wrapper const& other)
    {
        value=std::move(other.value);
        return *this;
    }

    move_on_copy_wrapper& operator=(move_on_copy_wrapper&& other)
    {
        value=std::move(other.value);
        return *this;
    }

};

その後、次のように使用できます。

int main()
{
    std::unique_ptr<int> p(new int(3));
    move_on_copy_wrapper<std::unique_ptr<int>> mp(std::move(p));

    [mp]()
    {
        std::cout<<"*mp.value="<<*mp.value<<std::endl;
    }
    ();

    std::cout<<"p="<<p.get()<<", mp="<<mp.value.get()<<std::endl;
}
于 2012-04-23T13:05:05.410 に答える
3

あなたの試み2はほとんどうまくいくでしょう。

欠落しているのはbind、パラメータを期待するように呼び出しに指示していないことです。

std::for_each(arr.begin(), arr.end(),
   std::bind([](const unique_ptr<int>& p, int& i){
      i += (*p);
   }, std::move(p), std::placeholders::_1)
);

は、のパラメータが渡されることを期待する必要があるplaceholders::_1という結果を伝えるために必要です。bindoperator()

これは、@marton78の回答にある提案でもあります

于 2015-03-27T00:42:21.893 に答える