[英]Why can't lvalue references bind to const const "forwarding references"?
"forwarding references" is in quotes because const
-qualified forwarding references aren't actually forwarding references, but I wanted to make it clear that I am specifically referring to function templates. “转发引用”用引号引起来,因为
const
限定的转发引用实际上并不是转发引用,但我想明确表示我特指的是函数模板。
Take the following test functions (code is duplicated to avoid :采取以下测试功能(代码重复以避免:
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
template <typename T, typename U> void print_types() {
cout << (is_const_v<remove_reference_t<T>> ? "const " : "")
<< typeid(T).name()
<< (is_rvalue_reference_v<T> ? " &&"
: is_lvalue_reference_v<T> ? " &"
: "")
<< ", " << (is_const_v<remove_reference_t<U>> ? "const " : "")
<< typeid(U).name()
<< (is_rvalue_reference_v<U> ? " &&"
: is_lvalue_reference_v<U> ? " &"
: "")
<< endl;
}
template <typename T> void print_rvalue_reference(T &&t) {
print_types<T, decltype(t)>();
}
template <typename T> void print_const_rvalue_reference(const T &&t) {
print_types<T, decltype(t)>();
}
int main() {
int i = 1;
const int j = 1;
print_rvalue_reference(1); // int, int &&
print_rvalue_reference(i); // int &, int &
print_rvalue_reference(j); // const int &, const int &
print_const_rvalue_reference(1); // int, const int &&
print_const_rvalue_reference(i); // error
print_const_rvalue_reference(j); // error
}
First, I wanted to note that print_rvalue_reference(j)
only works because print_rvalue_reference
never uses t
in a non- const
context.首先,我想指出
print_rvalue_reference(j)
仅起作用,因为print_rvalue_reference
从不在非const
上下文中使用t
。 If this were not the case, the template instantiation would fail.如果不是这种情况,模板实例化将失败。
I am confused why the last two calls in main
cause errors during compilation.我很困惑为什么
main
的最后两个调用会在编译过程中导致错误。 Reference collapsing allows using T = int &; const T &&
参考折叠允许
using T = int &; const T &&
using T = int &; const T &&
to become int &
and using T = const int &; const T &&
using T = int &; const T &&
变为int &
并using T = const int &; const T &&
using T = const int &; const T &&
to become const int &
, which means print_const_rvalue_reference<int &>(i)
and print_const_rvalue_reference<const int &>(j)
are valid. using T = const int &; const T &&
变为const int &
,这意味着print_const_rvalue_reference<int &>(i)
和print_const_rvalue_reference<const int &>(j)
是有效的。
Why does print_const_rvalue_reference(j)
deduce T to be int
instead of const int &
when print_rvalue_reference(j)
does deduce T to be const int &
?为什么
print_const_rvalue_reference(j)
演绎吨至是int
而不是const int &
当print_rvalue_reference(j)
并演绎吨至是const int &
? Are (true) forwarding references special-cased to yield int &
instead of int
as part of its deduction guide? (真)转发引用是否特殊情况下产生
int &
而不是int
作为其推导指南的一部分?
Actual forwarding references are indeed special-cased to deduce a reference type.实际的转发引用确实是特殊情况以推导出引用类型。 See [temp.deduct.call]/3 :
见[temp.deduct.call]/3 :
If
P
is a cv-qualified type, the top-level cv-qualifiers ofP
's type are ignored for type deduction.如果
P
是CV-合格的类型,顶级CV-预选赛P
的类型被忽略类型推演。 IfP
is a reference type, the type referred to byP
is used for type deduction.如果
P
是引用类型,则使用P
引用的类型进行类型推导。 ... IfP
is a forwarding reference and the argument is an lvalue, the type “lvalue reference toA
” is used in place ofA
for type deduction.... 如果
P
是转发引用并且参数是左值,则使用“左值引用A
”类型代替A
进行类型推导。
Thus, in the case where P
is const T&&
(which is not a forwarding reference), it is transformed to const T
and whether or not the argument is an lvalue doesn't affect the type deduction, since value category is not part of the argument's type.因此,在
P
是const T&&
(不是转发引用)的情况下,它被转换为const T
并且参数是否是左值不会影响类型推导,因为值类别不是参数的类型。 Instead, the deduction process simply attempts to find T
such that const T
is the same type as the argument (possibly with additional cv-qualification).相反,推导过程只是试图找到
T
使得const T
与参数的类型相同(可能带有额外的 cv 限定)。 In the case of i
and j
, this means T
is deduced as int
and the argument type is const int&&
.在
i
和j
的情况下,这意味着T
被推导出为int
并且参数类型是const int&&
。
But in the special forwarding reference case, while P
is still transformed from T&&
to T
, the fact that it was originally a forwarding reference results in the replacement of an argument type by the corresponding lvalue reference type (if the argument is an lvalue).但是在特殊的转发引用情况下,虽然
P
仍然从T&&
转换为T
,但它最初是转发引用的事实导致参数类型替换为相应的左值引用类型(如果参数是左值)。 Thus, in the case of i
, the transformed argument type is int&
, and in the case of j
, it is const int&
.因此,在
i
的情况下,转换后的参数类型是int&
,而在j
的情况下,它是const int&
。 In both cases, T
is deduced in such a way as to make it identical to the transformed argument type, which means T
is deduced as a reference type.在这两种情况下,
T
都以使其与转换后的参数类型相同的方式推导,这意味着T
被推导为引用类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.