簡體   English   中英

為什么左值引用不能綁定到 const const“轉發引用”?

[英]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進行類型推導。

因此,在Pconst T&& (不是轉發引用)的情況下,它被轉換為const T並且參數是否是左值不會影響類型推導,因為值類別不是參數的類型。 相反,推導過程只是試圖找到T使得const T與參數的類型相同(可能帶有額外的 cv 限定)。 ij的情況下,這意味着T被推導出為int並且參數類型是const int&&

但是在特殊的轉發引用情況下,雖然P仍然從T&&轉換為T ,但它最初是轉發引用的事實導致參數類型替換為相應的左值引用類型(如果參數是左值)。 因此,在i的情況下,轉換后的參數類型是int& ,而在j的情況下,它是const int& 在這兩種情況下, T都以使其與轉換后的參數類型相同的方式推導,這意味着T被推導為引用類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM