我对以下元组业务感到有些困惑:
int testint = 1;
float testfloat = .1f;
std::tie( testint, testfloat ) = std::make_tuple( testint, testfloat );
std::tuple<int&, float&> test = std::make_tuple( testint, testfloat );
使用std::tie
它可以工作,但直接分配给引用元组不会编译,给出
“错误:从'std :: tuple&lt; int,float&gt;'转换为非标量类型'std :: tuple&lt; int&amp;,float&amp;&gt;'required”
或
“没有合适的用户定义的转换,从std :: tuple&lt; int,float&gt;到std :: tuple&lt; int&amp;,float&amp;&gt;”
为什么呢?我仔细检查了编译器是否真的与分配给它的类型相同:
static_assert( std::is_same<decltype( std::tie( testint, testfloat ) ), std::tuple<int&, float&>>::value, "??" );
评估为真。
我还检查了online以查看它是否是msvc的错误,但所有编译器都给出了相同的结果。
答案 0 :(得分:20)
make_tuple
和tie
都会通过参数推断出返回的类型。但是tie
会根据推导出的类型生成左值引用类型,而make_tuple
会生成一个实际的元组。
std::tuple<int&, float&> a = std::tie( testint, testfloat );
std::tuple<int , float > b = std::make_tuple( testint, testfloat );
tie
的目标是制作一个临时元组来避免绑定对象的临时副本,不好的结果是,如果条目对象是本地临时对象,则不能return
tie
。
答案 1 :(得分:13)
std::tie()
函数实际上初始化了std::tuple<T&...>
引用的成员,其中std::tuple<T&...>
无法由句型std::tuple<T...>
初始化。操作std::tie()
执行并初始化相应的对象将表达如下:
std::tuple<int&, float&> test =
std::tuple<int&, float&>(testint, testfloat) = std::make_tuple(testint, testfloat);
(显然,您通常会使用与已绑定变量不同的值)。
答案 2 :(得分:1)
问题是rhs std::make_tuple(testint, testfloat)
没有返回引用数组,它返回std::tuple<int, int>
,这是一个临时值,它的值不能绑定到lvalue-references。如果需要引用元组,可以使用辅助函数std::ref
:
auto test = std::make_tuple(std::ref(a), std::ref(b));
// ^^^^^^^^^^^ ^^^^^^^^^^^
这与tie
之间的区别在于引用在构造时由std::tie(a, b)
初始化。
答案 3 :(得分:-1)
我想,因为它们是不同的类型,并且没有从一个到另一个的转换,但是有一个模板化的复制赋值运算符,在绑定的情况下有效。
检查代码
#include <tuple>
#include <iostream>
int main() {
std::tuple<int> a{};
std::cout << std::get<0>(a) << std::endl;
std::tuple<float> b{1.f}; //note float type
a = b;
std::cout << std::get<0>(a) << std::endl;
}
output: 0 1
建议,它可能是正确的。