std :: tie如何工作?
我已经使用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 }
但是这个黑魔法是如何工作的? 如何由std::tie
创build一个临时变更a
和b
? 我觉得这更有趣,因为它是一个图书馆function,而不是一个语言function,所以肯定是我们可以实现自己和理解的东西。
为了澄清核心概念,我们把它简化为一个更基本的例子。 尽pipestd::tie
对返回更多值(一个元组)的函数是有用的,但我们可以很好地理解它,只有一个值:
int a; std::tie(a) = std::make_tuple(24); return a; // 24
为了前进,我们需要知道的事情:
-
std::tie
构造并返回一个引用的元组。 -
std::tuple<int>
和std::tuple<int&>
是两个完全不同的类,它们之间没有任何连接,除了它们是从同一个模板std::tuple
。 -
元组有一个
operator=
接受不同types(但是相同的数字)的元组,其中每个成员是单独分配的 – 从cppreference :template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );
(3)对于所有我,将
std::get<i>(other)
分配给std::get<i>(*this)
。
下一步是摆脱那些只有你自己的方式的function,所以我们可以将代码转换为:
int a; std::tuple<int&>{a} = std::tuple<int>{24}; return a; // 24
下一步是要看到这些结构内发生了什么。 为此,我为std::tuple<int>
和Tr
取代std::tuple<int&>
创build了2个T
取代,剥离到我们的操作的最小值:
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 }
最后,我喜欢摆脱所有的结构(好吧,这不是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 }
所以基本上, std::tie(a)
初始化一个数据成员引用。 std::tuple<int>(24)
创build一个值为24
的数据成员,赋值给第一个结构中的数据成员引用赋值24。 但是由于该数据成员是一个绑定到a
的引用,所以基本上赋值为24
。
这不能以任何方式回答你的问题,但是让我发表吧,因为C ++ 17基本上已经准备就绪(有编译器支持),所以在想知道过时的东西是如何工作的时候,可能值得看看当前的未来,C ++的版本也可以工作。
使用C ++ 17,你几乎可以从std::tie
中获得所谓的结构化绑定 。 他们也是这样做的(好吧, 不一样 ,但他们有相同的净效果),尽pipe你需要input更less的字符,它不需要库的支持,而且你也有能力引用,如果碰巧你想要什么。
(请注意,在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