如果我有代码
#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);
}
我收到错误
/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);
^
我发现最接近的是this question,但问题似乎是关于从std::make_tuple
返回的元组进行初始化,这是一个右值。然而,foo
非常值得一提。为什么这不起作用?这与使用std::tie
?
答案 0 :(得分:1)
2014-12-23的Github草案,[tuple.cnstr]
template <class... UType> constexpr tuple(tuple<UTypes...>&& u);
18 需要:
sizeof...(Types) == sizeof...(UTypes)
。 对于所有 i ,is_constructible<Ti, Ui&&>::value
为true
。20 备注:此构造函数不得参与 重载决策,除非
UTypes
中的每个类型都是隐式的 可转换为Types
中的相应类型。
备注:部分定义了SFINAE。请注意,与需要:部分的不同之处在于要求使用is_convertible
而不是is_constructible
。
在OP的示例中,这会导致检查is_convertible<float, float&>
,这是错误的:float
xvalue无法绑定到float
左值引用:
is_convertible
[meta.rel] / 4
给出以下函数原型:
template <class T> add_rvalue_reference_t<T>::type create() noexcept;
当且仅当以下vode格式正确时,才应满足模板特化
is_convertible<From, To>
的谓词条件,包括对函数返回类型的任何隐式转换:To test() { return create<From>(); }
下面,
float& test() {
return create<float>();
}
格式错误,create<float>()
返回float&&
,即xvalue。结果不能绑定到左值引用。
众所周知,tuple
的构造并不完美;例如,请参阅proposal N3680,其中也提到LWG defect 2051。
然而,似乎没有人在OP中解决这个问题。