Ответ 1
Если вы еще никогда не ссылаетесь на эту переменную, компилятор разрешил переместить ее в результирующий объект функции?
Нет. Единственная ситуация, когда компилятору разрешено заменять копию движением, - это те же ситуации, когда разрешено выполнять копирование. Эти ситуации включают возвращение локального объекта по значению или инициализацию объекта с временным. В этих случаях компилятору разрешается копировать копию, создавая источник и нацеливая один и тот же объект. Если компилятор не может это сделать по какой-либо причине, он должен рассматривать исходный объект как rvalue относительно разрешения перегрузки для выбора соответствующего конструктора для целевого объекта. В вашем случае, однако, файл является Lvalue, и ни один из случаев сверху не применяется. Вам нужно будет использовать явный ход.
К сожалению, С++ 11 не имеет синтаксиса для "захвата перемещения". ИМХО, это позор. Но std:: bind поддерживает это. Должно быть возможно совместить std:: bind с выражением лямбда следующим образом:
void foo(char const* p) {
string s = p;
auto fun = bind([](string const& s){
...
},move(s));
fun();
}
чтобы строка перемещалась в объект функции.
Если вы намерены вызывать эту функцию только один раз и хотите снова перенести строку из объекта функции, вы можете использовать неконстантную ссылку:
void foo(char const* p) {
string s = p;
auto fun = bind([](string & s) {
some_other_func(move(s));
},move(s));
fun();
}
Обратите внимание, что если вы не хотите использовать bind здесь, но пусть конструктор лямбда-объекта создает копию s, для перемещения строки из объекта функции требуется ключевое слово mutable:
void foo(char const* p) {
string s = p;
auto fun = [=]() mutable {
// ^^^^^^^
some_other_func(move(s));
};
fun();
}
поскольку в противном случае функция operator() типа замыкания будет const-qual, что, в свою очередь, делает s
строкой с константой.
В С++ 14 предложение lambda capture стало немного более гибким. Теперь мы можем написать
void foo(char const* p) {
string s = p;
auto fun = [s=move(s)]() mutable { // #1
some_other_func(move(s)); // #2
};
fun();
}
где # 1 перемещает значение строки в лямбда-объект, а # 2 перемещает значение строки (в зависимости от того, как some_other_func
объявлено точно).