簡體   English   中英

如何在std :: for_each中為一個lambda捕獲std :: unique_ptr“by move”

[英]How to capture std::unique_ptr “by move” for a lambda in std::for_each

我正在學習c ++ 11中的新功能並遇到了這個問題。 我想通過在lambda中移動它作為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沒有指定移動語法。

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.

這個練習的主要目的是了解如何在lambda中捕獲可移動變量,該lambda被緩存以供以后使用。

更新:您可以從C ++ 14開始捕獲lambda中的可移動變量。

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

在C ++ 11中,您無法以任何直接的方式將可移動變量捕獲到lambda中。

通過復制或引用捕獲Lambda。 因此,要捕獲僅移動變量,必須將其包裝在復制=>移動的對象(例如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;
}

你的嘗試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必須告訴bind的結果,它應該期望為其operator()傳遞給它的參數。

這也是@ marton78 在這里給出的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM