Непонятный синтаксис с std::tie

Я просто читаю немного о кортежах.

Теперь мне непонятен следующий синтаксис:

std::tie (myint, std::ignore, mychar) = mytuple;

Нетрудно понять, что он делает, НО что происходит с точки зрения языка? Мы каким-то образом присваиваем возвращаемое значение функции?


person Michael    schedule 20.11.2016    source источник


Ответы (4)


НО что происходит с точки зрения языка? Мы каким-то образом присваиваем возвращаемое значение функции?

Да, это может быть допустимо, в зависимости от типа возвращаемого значения функции. В основном есть два способа, которыми это может быть допустимо: во-первых, функция может возвращать ссылку lvalue на объект.

int i;
int &f() { return i; }
int main() { f() = 1; } // okay, assigns to i

Во-вторых, функции могут возвращать пользовательские типы с реализацией оператора =, который можно вызывать для rvalue:

struct S { void operator=(int) { } };
S f() { return {}; }
int main() { f() = 1; } // okay, calls S::operator=

Последнее — это то, что происходит с std::tie.

person Community    schedule 20.11.2016
comment
Обратите внимание, что для C++ structs и classes, пока ссылки rvalue на *this не появились в C++11, всегда можно было присвоить, даже если это временно! operator= будет работать, даже если результат будет отброшен. Здесь интересно то, что назначение tie делает что-то полезное. - person Yakk - Adam Nevraumont; 21.11.2016

std::tie(myint, std::ignore, mychar) возвращает тип
std::tuple<int&, decltype((std::ignore)), char&>, где int& — это ссылка на myint, а char& — на mychar.

Когда этому возвращенному кортежу ссылок присваивается mytuple, каждое значение в mytuple присваивается соответствующей ссылке, хранящейся в возвращенном кортеже. Это приводит к обновлению myint и mychar на месте.

std::tie(myint, std::ignore, mychar)             // <-- expression
std::tuple<int&, decltype((std::ignore)), char&> // <-- type

std::tie(myint, std::ignore, mychar)             = mytuple;
std::tuple<int&, decltype((std::ignore)), char&> = std::tuple<int, T, char>&;
// functions as
            std::tuple<int , T                      , char >&
//          ↓↓         =     =                        =    ↓↓
            std::tuple<int&, decltype((std::ignore)), char&>

// end result:
myint  = std::get<0>(mytuple);
mychar = std::get<2>(mytuple);
int&   = int&;
char&  = char&;
person ildjarn    schedule 20.11.2016
comment
@Т.С. : Конечно! Спасибо. - person ildjarn; 21.11.2016

tie возвращает кортеж ссылок. Вы присваиваете этому кортежу, что означает присваивание по элементам кортежа (за исключением полей std::ignored). Поскольку элементы этого кортежа на самом деле являются ссылками, вместо этого вы назначаете связанные элементы.

person krzaq    schedule 20.11.2016

Из ссылки cpp «Создает кортеж ссылок lvalue на свои аргументы или экземпляры std::ignore».

В этом смысле это не сильно отличается от того, когда вы присваиваете возвращаемое значение оператора [], как в

vec[3]=5;

Мы просто должны упомянуть, что C++ 17 имеет структурированные привязки auto [a,b,c] = и std::ignore со структурированными привязками?

person Johan Lundberg    schedule 20.11.2016
comment
Но тогда это в основном назначение rvalue, верно? (Что не запрещено в С++) - person Michael; 21.11.2016
comment
@Michael кортеж из tie действительно является rvalue - person krzaq; 21.11.2016