16

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

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<int, float>' 转换为非标量类型 'std::tuple<int&, float&>' 请求”

或者

“没有合适的用户定义从 std::tuple<int, float> 到 std::tuple<int&, float&> 的转换”

为什么?我仔细检查了编译器是否真的与通过执行此操作分配给的类型相同:

static_assert( std::is_same<decltype( std::tie( testint, testfloat ) ), std::tuple<int&, float&>>::value, "??" );

评估为真。

我也上网查了一下是不是msvc的问题,但是所有编译器的结果都是一样的。

4

4 回答 4

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

于 2013-11-05T22:38:25.793 回答
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);

(显然,您通常会使用与已绑定变量不同的值)。

于 2013-11-05T22:34:53.377 回答
1

问题是 rhsstd::make_tuple(testint, testfloat)不返回引用数组,而是返回std::tuple<int, int>,这是一个临时值,其值不能绑定到左值引用。如果需要引用元组,可以使用辅助函数std::ref

auto test = std::make_tuple(std::ref(a), std::ref(b));
//                          ^^^^^^^^^^^  ^^^^^^^^^^^

这和之间的区别在于tie引用是由std::tie(a, b)on 构造初始化的。

于 2013-11-05T22:35:42.037 回答
-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

建议,这可能是正确的。

于 2014-09-11T12:54:26.380 回答