简体   繁体   English

使用衰减与完美转发

[英]Using decay with perfect forwarding

Assume we have 2 functions:假设我们有两个函数:

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};
}

and we call them like this:我们这样称呼它们:

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&

depspite the similar deducing in both functions, in the 2nd function I have to use std::decay_t to compile the application.尽管两个函数中的推导相似,但在第二个函数中,我必须使用 std::decay_t 来编译应用程序。 Why it is so?为什么会这样?

I use Visual studio 2019 with the /std:c++17 flag我使用带有 /std:c++17 标志的 Visual Studio 2019

When you have a function like当你有一个像

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

then T is only going to get deduced as a non reference type.那么T只会被推导出为非引用类型。 If you give it a int& , then T becomes int so that t becomes a int& .如果你给它一个int& ,那么T变成int这样t就变成一个int& Because of that you do not need to use decay .因此,您不需要使用decay

In

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

If you pass a int& then T gets deduced as a int& , and then reference collapsing rules turn int& && into int& for the type of t .如果您传递int&T被推导出为int& ,然后引用折叠规则将int& &&转换为int&类型的t This means that without decay you would try to make a std::initializer_list<int&> which you can't do.这意味着在没有decay您会尝试制作一个您无法做到的std::initializer_list<int&>

It is not correct to say that the deduced types are identical:说推导出的类型相同是不正确的:

#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;
}

prints:印刷:

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&]

In your situation std::decay removes the extra reference that is present in the second example.在您的情况下, std::decay删除了第二个示例中存在的额外引用。

Because T may or may not be a reference type:因为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