Initialize tuple of references with reference to tuple

梦想与她 提交于 2019-12-06 06:04:56

问题


If I have the code

#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);
}

I get the error

/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);

^

The closest thing I've found is this question, but the problem there seems to be about initializing with a tuple returned from std::make_tuple, which is an rvalue. foo, however, is very much an lvalue. Why does this not work? How is this different from using std::tie?


回答1:


Github draft from 2014-07-23, [tuple.cnstr]

template <class... UType> constexpr tuple(tuple<UTypes...>&& u);

18Requires: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true for all i.

20Remark: This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types.

The Remarks: section defines the SFINAE. Note how it's different from the Requires: section by requiring the use of is_convertible instead of is_constructible.

In the OP's example, this leads to the check is_convertible<float, float&>, which is false: a float xvalue cannot be bound to a float lvalue reference:

is_convertible [meta.rel]/4

Given the following function prototype:

template <class T>
add_rvalue_reference_t<T>::type create() noexcept;

the predicate condition for a template specialization is_convertible<From, To> shall be satisfied if and only if the following vode would be well-formed, including any implicit conversions to the return type of the function:

To test() {
    return create<From>();
}

Here,

float& test() {
    return create<float>();
}

is ill-formed, create<float>() returns a float&&, that is, an xvalue. The result cannot be bound to an lvalue-reference.


It is well-known that the construction of tuple is not perfect; see for example proposal N3680, which also addresses LWG defect 2051.

None of those seem to address the issue in the OP, however.



来源:https://stackoverflow.com/questions/24918426/initialize-tuple-of-references-with-reference-to-tuple

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!