参考元组初始化引用元组

Dan*_*Dan 5 c++ tuples reference

如果我有代码

#include <tuple>

using Vec3 = std::tuple<float, float, float>;
using Vec3Ref = std::tuple<float&, float&, float&>;

void stuff ()
{
  Vec3 foo (0,0,0);
  Vec3Ref bar (foo);
}
Run Code Online (Sandbox Code Playgroud)

我收到错误

/usr/include/c++/4.6/tuple:100:4: error: binding of reference to type 'float' to
a value of type 'const float' drops qualifiers

: _M_head_impl(std::forward<_UHead>(__h)) { }

^ ~~~~~~~~~~~~~~~~~~~~~~~~~

//snip...

/usr/include/c++/4.6/tuple:257:11: note: in instantiation of function template
specialization 'std::_Tuple_impl<0, float &, float &, float &>::_Tuple_impl
<float, float, float>' requested here

: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))

^

18 : note: in instantiation of function template specialization
'std::tuple::tuple' requested here

Vec3Ref bar (foo);

^
Run Code Online (Sandbox Code Playgroud)

我发现的最接近的是这个问题,但问题似乎是关于使用从返回的元组进行初始化std::make_tuple,这是一个右值。foo然而,它在很大程度上是一个左值。为什么这不起作用?这与使用有何不同std::tie

dyp*_*dyp 2

2014年7月23日的Github草案,[tuple.cnstr]

template <class... UType> constexpr tuple(tuple<UTypes...>&& u);
Run Code Online (Sandbox Code Playgroud)

18 要求: sizeof...(Types) == sizeof...(UTypes) . is_constructible<Ti, Ui&&>::valuetrue为了所有的

20 备注:此构造函数不应参与重载决策,除非 中的每个类型UTypes都可以隐式转换为 中对应的类型Types

备注部分定义了 SFINAE。请注意它与Requires:部分的不同之处在于要求使用 ofis_convertible而不是is_constructible

在OP的示例中,这会导致检查is_convertible<float, float&>,这是错误的:floatxvalue不能绑定到floatlvalue引用:

is_convertible[元.rel]/4

给出以下函数原型:

template <class T>
add_rvalue_reference_t<T>::type create() noexcept;
Run Code Online (Sandbox Code Playgroud)

is_convertible<From, To>当且仅当以下 vode 格式良好(包括对函数返回类型的任何隐式转换)时,才应满足模板特化的谓词条件:

To test() {
    return create<From>();
}
Run Code Online (Sandbox Code Playgroud)

这里,

float& test() {
    return create<float>();
}
Run Code Online (Sandbox Code Playgroud)

格式错误,create<float>()返回 a float&&,即 xvalue。结果不能绑定到左值引用。


众所周知,建设tuple并不完美;例如,参见提案 N3680,它也解决了LWG 缺陷 2051

然而,这些似乎都没有解决OP中的问题。