简体   繁体   中英

Unclear syntax with std::tie

I'm just reading a bit about tuples .

Now the following syntax is not clear to me:

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

It's not difficult to grasp what it does, BUT what happens from a language point of view? We are somehow assigning to the return value of a function?

BUT what happens from a language point of view? We are somehow assigning to the return value of a function?

Yes, that can be valid, depending on the function's return type. There are mainly two ways in which it can be valid: firstly, the function may return an lvalue reference to an object.

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

Secondly, functions may return user-defined types with an = operator implementation that can be called on rvalues:

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

The latter is what's happening with std::tie .

The return type of std::tie(myint, std::ignore, mychar) is
std::tuple<int&, decltype((std::ignore)), char&> , wherein the int& is a reference to myint and the char& is a reference to mychar .

When mytuple is assigned to this returned tuple-of-references, each value in mytuple is assigned to the respective reference stored in the returned tuple. This has the effect of updating myint and mychar in place.

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&;

tie returns a tuple of references. You're assigning to that tuple, which means tuple-memberwise assignment (with the exception with std::ignore d fields). Because that tuple's elements are actually references, you're assigning to the tied elements instead.

From cpp reference "Creates a tuple of lvalue references to its arguments or instances of std::ignore. "

In that sense, it's not that different from when you assign to the return value of operator [] as in

vec[3]=5;

We just have to mention that C++17 has structured bindings auto [a,b,c] = , and std::ignore with structured bindings?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM