C++ std::tie 是如何工作的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43762651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does std::tie work?
提问by bolov
I've used std::tie
without giving much thought into it. It works so I've just accepted that:
我std::tie
没有考虑太多就使用了。它有效,所以我刚刚接受了这一点:
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 magicwork? 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.
但是这个黑魔法是如何运作的呢?如何通过std::tie
更改a
和创建临时b
?我觉得这更有趣,因为它是一个库特性,而不是一个语言特性,所以它肯定是我们可以自己实现和理解的东西。
回答by bolov
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:
为了阐明核心概念,让我们将其简化为更基本的示例。虽然std::tie
对于返回(一组)更多值的函数很有用,但我们可以只用一个值来理解它:
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)
.
std::tie
构造并返回一个引用元组。std::tuple<int>
并且std::tuple<int&>
是 2 个完全不同的类,它们之间没有联系,除了它们是从同一个模板生成的,std::tuple
.tuple 有一个
operator=
接受不同类型(但相同编号)的元组,其中每个成员都是单独分配的——来自cppreference:template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );
(3) 对于所有的 i,分配
std::get<i>(other)
给std::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:
下一步是查看这些结构内部究竟发生了什么。为此,我创建了 2 种类型的T
取代基std::tuple<int>
和Tr
取代基std::tuple<int&>
,精简到我们操作的最低限度:
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):
最后,我喜欢把所有的结构都去掉(嗯,它不是 100% 等效的,但它对我们来说已经足够接近了,并且足够明确以允许它):
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(a)
初始化一个数据成员引用到a
. std::tuple<int>(24)
创建一个具有 value 的数据成员24
,并且赋值将 24 分配给第一个结构中的数据成员引用。但是由于该数据成员是绑定到 的引用a
,因此基本上分配24
给a
。
回答by Damon
This does not answer your question in any way, but let me post it anyway because C++17 is basically ready (with compiler support), so while wondering how the outdated stuff works, it is probably worth looking at how the current, and future, version of C++ works, too.
这并没有以任何方式回答你的问题,但无论如何让我发布它,因为 C++17 基本上已经准备好了(有编译器支持),所以在想知道过时的东西是如何工作的时候,可能值得看看当前的,以及未来,C++ 版本也可以工作。
With C++17 you can pretty much scratch std::tie
in favour of what is called structured bindings. They do the same (well, not the same, but they have the same net effect), although you need to type fewer characters, it does not need library support, and you alsohave the ability to take references, if that happens to be what you want.
使用 C++17,您几乎可以从头开始std::tie
支持所谓的结构化绑定。他们做同样的事情(嗯,不一样,但他们有相同的净效果),虽然你需要输入更少的字符,它不需要库支持,而且你也有能力获取引用,如果碰巧的话你想要什么。
(Note that in C++17 constructors do argument deduction, so make_tuple
has become somewhat superfluous, too.)
(请注意,在 C++17 构造函数中进行参数推导,因此make_tuple
也变得有些多余。)
int a, b;
std::tie(a, b) = std::make_tuple(2, 3);
// C++17
auto [c, d] = std::make_tuple(4, 5);
auto [e, f] = std::tuple(6, 7);
std::tuple t(8,9); auto& [g, h] = t; // not possible with std::tie