std::tie 是如何工作的? [英] How does std::tie work?
问题描述
我使用了 std::tie
并没有考虑太多.它有效,所以我刚刚接受:
自动测试(){国际a, b;std::tie(a, b) = std::make_tuple(2, 3);//a 现在是 2,b 现在是 3返回 a + b;//5}
但是这个黑魔法是如何运作的?std::tie
创建的临时文件如何改变 a
和 b
?我觉得这更有趣,因为它是一个库特性,而不是一个语言特性,所以它肯定是我们可以自己实现和理解的东西.
为了阐明核心概念,让我们将其简化为更基本的示例.虽然 std::tie
对于返回(一组)更多值的函数很有用,但我们可以理解它只用一个值就可以了:
int a;std::tie(a) = std::make_tuple(24);返回一个;//24
为了继续前进,我们需要知道的事情:
std::tie
构造并返回一个引用元组.std::tuple
和std::tuple
是 2 个完全不同的类,它们之间没有联系,除了它们是从同一个模板生成,std::tuple
.tuple 有一个
<块引用>operator=
接受不同类型(但相同编号)的元组,其中每个成员都被单独分配——来自 cppreference:模板<类... UTypes >元组&运算符=(const tuple<UTypes...>&其他);
(3) 对于所有的 i,将
std::get(other)
赋值给std::get(*this)
.>
下一步是去掉那些只会妨碍你的函数,这样我们就可以将我们的代码转换成这样:
int a;std::tuple<int&>{a} = std::tuple<int>{24};返回一个;//24
下一步是查看这些结构内部究竟发生了什么.为此,我为 std::tuple<int>
和 Tr
取代基 std::tuple<int& 创建了两种类型的
,精简到我们操作的最低限度:T
取代基;>
struct T {//取代 std::tuple;整数 x;};struct Tr {//std::tuple<int&> 的取代基内部&xr;自动运算符=(const T& other){//std::get(*this) = std::get(other);xr = 其他.x;}};自动 foo(){一个;Tr{a} = T{24};返回一个;//24}
最后,我喜欢把所有的结构都去掉(嗯,这不是 100% 等价的,但对我们来说已经足够接近了,并且足够明确以允许它):
自动 foo(){一个;{//临时变量的块替换//Tr{a}内部&tr_xr = a;//T{24}int t_x = 24;//= (赋值)tr_xr = t_x;}返回一个;//24}
所以基本上,std::tie(a)
初始化对a
的数据成员引用.std::tuple
创建一个值为 24
的数据成员,并且赋值将 24 分配给第一个结构中的数据成员引用.但是由于该数据成员是绑定到 a
的引用,因此基本上将 24
分配给 a
.
I've used std::tie
without giving much thought into it. It works so I've just accepted that:
auto test()
{
int a, b;
std::tie(a, b) = std::make_tuple(2, 3);
// a is now 2, b is now 3
return a + b; // 5
}
But how does this black magic work? How does a temporary created by std::tie
change a
and b
? I find this more interesting since it's a library feature, not a language feature, so surely it is something we can implement ourselves and understand.
In order to clarify the core concept, let's reduce it to a more basic example. Although std::tie
is useful for functions returning (a tuple of) more values, we can understand it just fine with just one value:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
Things we need to know in order to go forward:
std::tie
constructs and returns a tuple of references.std::tuple<int>
andstd::tuple<int&>
are 2 completely different classes, with no connection between them, other that they were generated from the same template,std::tuple
.tuple has an
operator=
accepting a tuple of different types (but same number), where each member is assigned individually—from cppreference:template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );
(3) For all i, assigns
std::get<i>(other)
tostd::get<i>(*this)
.
The next step is to get rid of those functions that only get in your way, so we can transform our code to this:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
The next step is to see exactly what happens inside those structures.
For this, I create 2 types T
substituent for std::tuple<int>
and Tr
substituent std::tuple<int&>
, stripped down to the bare minimum for our operations:
struct T { // substituent for std::tuple<int>
int x;
};
struct Tr { // substituent for std::tuple<int&>
int& xr;
auto operator=(const T& other)
{
// std::get<I>(*this) = std::get<I>(other);
xr = other.x;
}
};
auto foo()
{
int a;
Tr{a} = T{24};
return a; // 24
}
And finally, I like to get rid of the structures all together (well, it's not 100% equivalent, but it's close enough for us, and explicit enough to allow it):
auto foo()
{
int a;
{ // block substituent for temporary variables
// Tr{a}
int& tr_xr = a;
// T{24}
int t_x = 24;
// = (asignement)
tr_xr = t_x;
}
return a; // 24
}
So basically, std::tie(a)
initializes a data member reference to a
. std::tuple<int>(24)
creates a data member with value 24
, and the assignment assigns 24 to the data member reference in the first structure. But since that data member is a reference bound to a
, that basically assigns 24
to a
.
这篇关于std::tie 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!