参考元组初始化引用元组 [英] Initialize tuple of references with reference to tuple
问题描述
如果我有代码
#include <元组>使用 Vec3 = std::tuple;使用 Vec3Ref = std::tuple<float&, float&, float>;空的东西(){vec3 foo (0,0,0);Vec3Ref 栏 (foo);}
我收到错误
/usr/include/c++/4.6/tuple:100:4: 错误:将引用绑定到类型float"到'const float' 类型的值删除限定符: _M_head_impl(std::forward<_UHead>(__h)) { }^ ~~~~~~~~~~~~~~~~~~~~~~~~~//剪.../usr/include/c++/4.6/tuple:257:11: 注意:在函数模板的实例化中专业化 'std::_Tuple_impl<0, float &, float &, float &>::_Tuple_impl<浮动,浮动,浮动>'在这里请求: _Inherited(static_cast&>(__in))^18:注意:在函数模板特化的实例化中'std::tuple::tuple' 在这里请求Vec3Ref 栏 (foo);^
我发现的最接近的是 这个问题,但问题似乎是用从 std::make_tuple
返回的元组进行初始化,这是一个右值.然而,foo
在很大程度上是一个左值.为什么这不起作用?这与使用 std::tie
有何不同?
Github 草稿于 2014-07-23,[tuple.cnstr]
<块引用>template constexpr 元组(元组&& u);
18 要求: sizeof...(Types) == sizeof...(UTypes)
.is_constructible
true
.
20 备注: 此构造函数不参与除非UTypes
中的每个类型都是隐式的,否则重载决议可转换为 Types
中对应的类型.
备注: 部分定义了 SFINAE.请注意它与 Requires: 部分的不同之处在于它要求使用 is_convertible
而不是 is_constructible
.
在 OP 的示例中,这导致检查 is_convertible
,这是错误的:float
xvalue 不能绑定到 float
左值参考:
is_convertible
[meta.rel]/4
给定以下函数原型:
template add_rvalue_reference_t::type create() noexcept;
模板特化的谓词条件 is_convertible
应满足当且仅当以下 vode 格式正确,包括任何隐式转换到函数的返回类型:
测试(){返回 create();}
这里,
float&测试() {return create();}
格式错误,create
返回一个 float&&
,即一个 xvalue.结果不能绑定到左值引用.
众所周知,tuple
的构造并不完美;参见例如提案N3680,其中还解决了 LWG 缺陷 2051.
然而,这些似乎都没有解决 OP 中的问题.
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
?
Github draft from 2014-07-23, [tuple.cnstr]
template <class... UType> constexpr tuple(tuple<UTypes...>&& u);
18 Requires:
sizeof...(Types) == sizeof...(UTypes)
.is_constructible<Ti, Ui&&>::value
istrue
for all i.20 Remark: This constructor shall not participate in overload resolution unless each type in
UTypes
is implicitly convertible to its corresponding type inTypes
.
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.
这篇关于参考元组初始化引用元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!