Вопрос по lambda, c++11, c++ – Как захватить std :: unique_ptr «по ходу» для лямбды в std :: for_each

12

Я изучаю новые функции в C ++ 11 и столкнулся с этой проблемой. Я хотел бы захватить unique_ptr, переместив его в лямбду в качестве аргумента для for_each.

настроить:

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

попытка 1 - не работает, так как unique_ptr не имеет конструктора копирования. C ++ 0x не определяет синтаксис передачи по ходу.

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

попытка 2 - использовать связывание, чтобы связать перемещенную копию p с функцией, которая принимает int & amp ;:

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

Компилятор жалуется, что'result' : symbol is neither a class template nor a function template.

Основная цель этого упражнения состоит в том, чтобы понять, как можно записать подвижную переменную в лямбду, которая кэшируется для последующего использования.

Этот вопрос уже задавалсяhere, Однако я не голосую за закрытие, поскольку ваш вопрос содержит альтернативное (хотя и не работающее) решение. Luc Touraille
Смотрите такжеhere. Luc Touraille

Ваш Ответ

2   ответа
3

Что вам не хватает, так это то, что вы не сказали своим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.Вот.

18

вы можете захватить подвижную переменную в лямбду с C ++ 14 года.

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

Вы не можете записать подвижную переменную в лямбду любым простым способом в C ++ 11.

Захват лямбды по копии или по ссылке. Таким образом, чтобы захватить переменную только для перемещения, вы должны заключить ее в объект, где copying = & gt; перемещение (например,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;
}
Компилятор не будет генерировать их из-за существования конструктора копирования и оператора назначения копирования.
& quot; Обратите внимание, что std :: bind также требует, чтобы его аргументы были копируемыми. & quot; Это не правда.std::bind может использоваться с типами только для перемещения.
AFAIK, std :: bind должен работать с подвижными аргументами. Однако в документации MSDN говорится, что все аргументы должны быть копируемыми. Энтони, какой компилятор ты используешь?msdn.microsoft.com/en-us/library/bb982702(v=vs.100).aspx Candy Chiu
ОК, я проверил:std::bind должен использоваться с аргументами только для перемещения, он просто создает результат только для перемещения. Однако на практике это не получается с MSVC 2010 и g ++ 4.7.
Ты серьезноneed реализовать двигательно-семантические функции, т.е.move_on_copy_wrapper(move_on_copy_wrapper&&) а такжеmove_on_copy_wrapper& operator=(move_on_copy_wrapper&&)? Сгенерированные компилятором не хватает?

Похожие вопросы