Answers:
为了阐明核心概念,我们将其简化为一个更基本的示例。尽管std::tie
对于返回更多值的函数很有用,但我们只用一个值就可以理解它:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
为了前进,我们需要知道的事情:
std::tie
构造并返回引用元组。std::tuple<int>
和std::tuple<int&>
是2个完全不同的类,它们之间没有任何联系,只是它们是从同一模板生成的std::tuple
。元组具有一个operator=
接受不同类型(但编号相同)的元组,其中每个成员都是从cppreference单独分配的:
template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );
(3)对于所有i,分配
std::get<i>(other)
给std::get<i>(*this)
。
下一步是摆脱那些只会妨碍您使用的功能,因此我们可以将代码转换为:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
下一步是确切了解这些结构内部发生的情况。为此,我T
为std::tuple<int>
和创建了2种类型的取代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
}
最后,我希望摆脱所有结构(嗯,它不是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)
初始化对的数据成员引用a
。std::tuple<int>(24)
创建一个具有value的数据成员24
,并且分配将24分配给第一个结构中的数据成员引用。但由于该数据成员是绑定到的引用a
,因此基本上分配24
给a
。
std::tuple
不是容器,至少在C ++术语中不是,与等不一样std::vector
。例如,您不能使用元组的常规方法进行迭代,因为它包含不同类型的对象。
这不会以任何方式回答您的问题,但是无论如何我还是要发布它,因为C ++ 17基本上已经准备就绪(具有编译器支持),因此在想知道过时的东西是如何工作的同时,可能值得看看最新的东西,以及将来,C ++版本也可以使用。
使用C ++ 17,您几乎可以从头开始std::tie
支持结构化绑定。它们执行相同的操作(嗯,不相同,但是它们具有相同的净效果),尽管您需要键入的字符较少,但不需要库支持,如果碰巧是,您也可以引用。你想要什么。
(请注意,在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
tie
结构化绑定不同的是,可以在无法默认构造的类型上使用结构化绑定。
std::tie()
自C ++ 17以来,它的用处要少得多,在C ++ 17中,结构化绑定通常是更好的选择,但它仍具有用途,包括分配给现有(不是同时新声明的)变量,以及简洁地做其他事情,例如交换多个变量或其他必须分配给参考。