分配给std :: tie和引用元组有什么区别?

时间:2013-11-05 22:27:14

标签: c++ reference tuples

我对以下元组业务感到有些困惑:

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的错误,但所有编译器都给出了相同的结果。

4 个答案:

答案 0 :(得分:20)

make_tupletie都会通过参数推断出返回的类型。但是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

建议,它可能是正确的。