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一个临时变更ab ? 我觉得这更有趣,因为它是一个图书馆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