[英]Why can't lvalue references bind to const const "forwarding references"?
“轉發引用”用引號引起來,因為const
限定的轉發引用實際上並不是轉發引用,但我想明確表示我特指的是函數模板。
采取以下測試功能(代碼重復以避免:
#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
}
首先,我想指出print_rvalue_reference(j)
僅起作用,因為print_rvalue_reference
從不在非const
上下文中使用t
。 如果不是這種情況,模板實例化將失敗。
我很困惑為什么main
的最后兩個調用會在編譯過程中導致錯誤。 參考折疊允許using T = int &; const T &&
using T = int &; const T &&
變為int &
並using T = const int &; const T &&
using T = const int &; const T &&
變為const int &
,這意味着print_const_rvalue_reference<int &>(i)
和print_const_rvalue_reference<const int &>(j)
是有效的。
為什么print_const_rvalue_reference(j)
演繹噸至是int
而不是const int &
當print_rvalue_reference(j)
並演繹噸至是const int &
? (真)轉發引用是否特殊情況下產生int &
而不是int
作為其推導指南的一部分?
實際的轉發引用確實是特殊情況以推導出引用類型。 見[temp.deduct.call]/3 :
如果
P
是CV-合格的類型,頂級CV-預選賽P
的類型被忽略類型推演。 如果P
是引用類型,則使用P
引用的類型進行類型推導。 ... 如果P
是轉發引用並且參數是左值,則使用“左值引用A
”類型代替A
進行類型推導。
因此,在P
是const T&&
(不是轉發引用)的情況下,它被轉換為const T
並且參數是否是左值不會影響類型推導,因為值類別不是參數的類型。 相反,推導過程只是試圖找到T
使得const T
與參數的類型相同(可能帶有額外的 cv 限定)。 在i
和j
的情況下,這意味着T
被推導出為int
並且參數類型是const int&&
。
但是在特殊的轉發引用情況下,雖然P
仍然從T&&
轉換為T
,但它最初是轉發引用的事實導致參數類型替換為相應的左值引用類型(如果參數是左值)。 因此,在i
的情況下,轉換后的參數類型是int&
,而在j
的情況下,它是const int&
。 在這兩種情況下, T
都以使其與轉換后的參數類型相同的方式推導,這意味着T
被推導為引用類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.