Я хочу, чтобы привязки в последней строке ссылались на объекты внутри владельца.
Давайте проигнорируем все новые языковые функции и вернемся к основам. Как вы ожидаете, что это будет работать?
int&& f() { return 0; }
int&& r = f();
Вы хотите, чтобы r
был ссылкой на локальную переменную внутри f
? Но это уничтожается в конце казни f()
. Этот код компилируется, но r
- это свисающая ссылка.
Единственный способ обеспечить это - обеспечить, чтобы f()
возвращал ссылку на объект, который определенно переживает функцию. Может быть, это локальный static
, может быть, он глобальный, может быть, это переменная-член класса, членом которого является f
, и т. Д .:
int global = 0;
int&& f() { return std::move(global); }
int&& r = f(); // okay, r is a reference to global, no dangling
Или, если это не имеет смысла, вам нужно вернуть объект по значению . Вы все еще можете взять ссылку на это. Или нет:
int f() { return 0; }
int&& r = f(); // okay, lifetime extension
int i = f(); // okay, prvalue elision
Те же базовые принципы применяются, когда мы добавляем все сложности tuple
и структурированных привязок. Либо возвращайте локальные, нестатические объекты по значению, либо возвращайте некоторые другие объекты по ссылке. Но не возвращайте локальные нестатические объекты по ссылке.
<ч />
В конечном итоге я пытаюсь создать вспомогательную функцию, чтобы мне не приходилось вводить четыре строки в функции каждый раз, когда я хочу создать нового владельца. Это моя попытка использовать структурированное связывание, чтобы сделать это проще.
Почему бы просто не сделать тип?
struct X {
X() : owner(controller, ancillary, compressor) { }
X(X const&) = delete;
X& operator=(X const&) = delete;
State<Controller> controller;
State<Ancillary> ancillary;
State<Compressor> compressor;
Owner owner;
};
// lifetime extension on the X, no copies anywhere
// note that owner is last
auto&& [controller, ancillary, compressor, owner] = X();
// no lifetime extension, but also no copies because
// prvalue elision
auto [controller, ancillary, compressor, owner] = X();