Передача результата std :: forward_as_tuple () нескольким функциям, которые могут перемещаться из членов-ссылок rvalue этого объекта? - PullRequest
4 голосов
/ 13 января 2012

Редактировать: Я думаю, что наиболее вероятный вариант использования того, о чем я спрашиваю, это при создании функции, которая получает кортеж rvalue-ссылок от std::forward_as_tuple().

Причина, по которой этот вопрос пришел в голову, состоит в том, что я проверял членов объектов, переданных инициализаторам конструктора, чтобы определить, являются ли они ссылками на rvalue (я открыт для советов, говорящих мне, что это неправильно, неправильно, неправильно... надеюсь, за этим последует эмпирическое правило, чтобы избежать этого в будущем, но это то, что вызвало вопрос).Мне пришло в голову, что в несколько ином контексте я мог бы в конечном итоге передать объект, имеющий элементы rvalue-reference, нескольким функциям (или функциональным объектам), которые я могу контролировать или не контролировать, которые могут выполнять перемещения из этих членов.

template<typename... Args>
void my_func(std::tuple<Args...>&& tup) {

    //if tup's members are rvalue references,
    //and this function moves guts from tup members, then...
    func_i_dont_control(tup); 

    //what happens here if moves are done on the same members?
    another_func_i_dont_control(std::move(tup));
}

Я смотрел на Использовать ссылочные члены rvalue? , наряду с некоторыми другими обсуждениями ссылочных членов rvalue, но я не совсем в состоянии окончательно разобраться в этом.

Я не просто спрашиваю, что произойдет, но должен ли этот сценарий случиться или вообще вообще случиться, и какие ключевые правила следует помнить при передаче объектов, содержащих элементы rvalue-reference.

Ответы [ 2 ]

1 голос
/ 13 января 2012

В этом коде func_i_dont_control не может автоматически украсть параметр. Только rvalue связываются с rvalue ссылками, а именованная переменная не является rvalue. Ваш код либо не компилируется, либо func_i_dont_control (перегружен) не использует семантику перемещения.

Чтобы дать func_i_dont_control возможность украсть кортеж (связать кортеж со ссылкой на rvalue), его нужно явно привести к rvalue с помощью std::move(tup).

(Функция, принимающая ссылку на lvalue, не должна уходить от нее, иначе мы действительно не сможем сказать, что произойдет.)


Редактировать Но вопрос, похоже, не в самом кортеже, а в его членах. Опять же, эти члены не будут rvalues, поэтому func_i_dont_control нужно будет явно их переместить. Я не думаю, что у него есть «моральное право» * делать это, если только он не получает весь кортеж в качестве значения, чего не происходит в вашей функции.

* При использовании семантики перемещения вы должны следовать определенным правилам. По сути, вы можете привести что угодно к rvalue и перейти от него, не имеет значения, имеете ли вы дело со ссылками lvalue или rvalue. Пока вы будете следовать этим рекомендациям, семантика перемещения будет работать правильно. Если вы начнете приводить значения к значениям, игнорирующим эти рекомендации, объекты начнут исчезать после вызовов функций и т. Д.

1 голос
/ 13 января 2012

Использование кортежей и шаблонов с переменными значениями, кажется, отвлекает от сути вопроса, поэтому позвольте мне перефразировать его:

void func(std::unique_ptr<Foo>&& foo) {
  std::unique_ptr<Foo> bar1(std::move(foo));
  std::unique_ptr<Foo> bar2(std::move(foo));
}

Что здесь происходит? Ну, bar2 всегда содержит нулевой указатель (и bar1 может, в зависимости от исходного значения foo).

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

...