簡體   English   中英

使用衰減與完美轉發

[英]Using decay with perfect forwarding

假設我們有兩個函數:

template <typename T> void callDecayExample1(T& t)
{
    std::initializer_list<T> testList2{ 1, 2, 3 };
}

template <typename T> void callDecayExample2(T&& t)
{
    std::initializer_list<std::decay_t<T>> testList{1, 2, 3};
}

我們這樣稱呼它們:

const int& i = 2;
int j = 10;
int& ref_j = j;

callDecayExample1(i);       // deduced as const int&
callDecayExample1(ref_j);// deduced as int&
callDecayExample1(j);   // deduced as int&

callDecayExample2(i);       // deduced as const int&
callDecayExample2(ref_j);// deduced as int&
callDecayExample2(j);   // deduced as int&

盡管兩個函數中的推導相似,但在第二個函數中,我必須使用 std::decay_t 來編譯應用程序。 為什么會這樣?

我使用帶有 /std:c++17 標志的 Visual Studio 2019

當你有一個像

template <typename T> void callDecayExample1(T& t)
{
    std::initializer_list<T> testList2{ 1, 2, 3 };
}

那么T只會被推導出為非引用類型。 如果你給它一個int& ,那么T變成int這樣t就變成一個int& 因此,您不需要使用decay

template <typename T> void callDecayExample2(T&& t)
{
    std::initializer_list<std::decay_t<T>> testList{1, 2, 3};
}

如果您傳遞int&T被推導出為int& ,然后引用折疊規則將int& &&轉換為int&類型的t 這意味着在沒有decay您會嘗試制作一個您無法做到的std::initializer_list<int&>

說推導出的類型相同是不正確的:

#include <iostream>

template <typename T>
void printType()
{
  std::cerr << __PRETTY_FUNCTION__ << std::endl;
}

template <typename T>
void callDecayExample1(T& t)
{
  printType<T>();
  std::initializer_list<T> testList2{1, 2, 3};
}

template <typename T>
void callDecayExample2(T&& t)
{
  printType<T>();
  std::initializer_list<std::decay_t<T>> testList{1, 2, 3};
}

int main()
{
  const int i = 0;
  int j = 1;
  int& ref_j = j;

  callDecayExample1(i);
  callDecayExample1(ref_j);
  callDecayExample1(j);

  callDecayExample2(i);
  callDecayExample2(ref_j);
  callDecayExample2(j);

  return 0;
}

印刷:

void printType() [with T = const int]
void printType() [with T = int]
void printType() [with T = int]

void printType() [with T = const int&]
void printType() [with T = int&]
void printType() [with T = int&]

在您的情況下, std::decay刪除了第二個示例中存在的額外引用。

因為T可能是也可能不是引用類型:

template <typename T> void callDecayExample2(T&& t)
{
    if constexpr (std::is_same<T, int&>::value)
        std::initializer_list<std::decay_t<T>> testList{ 1, 2, 3 };
    else
        std::initializer_list<T> testList{ 1, 2, 3 };
}

int val = 5;
callDecayExample2(5)   // T = int
callDecayExample2(val) // T = int&

暫無
暫無

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

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