2017-02-14 5 views
17

Я пытаюсь скомпилировать следующий код:Почему конструктор перемещения не вызывается при перемещении в лямбда?

#include <utility> 

struct C2 { 
     C2() = default; 
     C2(C2 const&) = delete; 
     C2(C2&&) = default; 
}; 

int main() { 
     C2 p2; 
     ([p2_1{ std::move(p2) }]() { 
       auto p2_2 = std::move(p2_1); // <--- 
     })(); 
     return 0; 
} 

Однако это не компилируется и выдает ошибку, что назначение p2_2 звонит удаленную функцию, а именно конструктор копирования. Обратите внимание, что переход на p2_1 в порядке. Почему это не использует конструктор перемещения?

+0

Я не эксперт лямбды, но вместо того, чтобы переместить 'p2' в' p2_1', захватив 'p2_1', а затем переместив' p2_1' в 'p2_2', почему бы просто [захватить' p2' ссылкой и перемещать это прямо к 'p2_2'] (http://ideone.com/PsBQMJ)? '[& p2]() {auto p2_2 = std :: move (p2); } ' –

+2

@RemyLebeau это очень урезанная версия того, что я на самом деле делал. Я продолжал удалять детали, пока не получил небольшой образец, который все еще имеет проблему. Фактический код нуждался в лямбда, чтобы пережить область функций, в которой она была объявлена, поэтому захват по ссылке не был вариантом. – baruch

+0

ОК, это имеет смысл тогда. –

ответ

27

Уловка заключается в том, что operator() типа анонимного класса представляет собой const по умолчанию. Это означает, что вы не можете перейти от p2_1, так как this лямбда находится в функции const&. Что вам нужно сделать, это использовать ключевое слово mutable как

int main() { 
     C2 p2; 
     ([p2_1{ std::move(p2) }]() mutable { 
       auto p2_2 = std::move(p2_1); // <--- 
     })(); 
     return 0; 
} 

Что делает функцию нон сопзИте, которая, в свою очередь означает, что вы можете мутировать его член. Это позволяет вам перемещать p2_1 вместо того, чтобы его копировать.

+0

Это относится также к захвату 'this', тоже? Кажется, я могу назвать неконстантные функции, используя захваченный указатель 'this' – baruch

+0

@baruch. Это хороший вопрос. AFAIK, когда вы фиксируете 'this', он сохраняет свой тип значения, поэтому, если он не const, он будет не const в лямбда. – NathanOliver

+3

@baruch 'this' is const, но' * this' нет. Это указатель const, но не указатель на константу. – immibis

Смежные вопросы