10

所以我想练习使用std::forward并创建了一个Test有 2 个构造函数的类。1个with T&,另一个withT&&作为过载。T&打印lvalueT&&打印rvalue以便我知道正在使用哪个构造函数。我在堆栈上创建了 2 个类实例,令我惊讶的是,它们都使用了T&&重载。

#include <iostream>
#include <type_traits>
#include <utility>

template <class T> auto forward(T &&t) {
  if constexpr (std::is_lvalue_reference<T>::value) {
    return t;
  }
  return std::move(t);
}

template <class T> class Test {
public:
  Test(T &) { std::cout << "lvalue" << std::endl; };
  Test(T &&) { std::cout << "rvalue" << std::endl; };
};

int main() {
  int x = 5;
  Test<int> a(forward(3));
  Test<int> b(forward(x));
  return 0;
}

我尝试使用原始std::forward函数并实现它,但两次都打印了rvalue x2。我究竟做错了什么?

4

1 回答 1

14

您的问题源于forward. 您将auto其用作不会为您推断出引用的返回类型。这意味着当您返回时,无论它从哪个分支返回,您都按值返回,这意味着您有一个纯右值。

您需要的是decltype(auto)根据返回语句返回右值或左值引用。使用

template <class T> decltype(auto) forward(T &&t) {
  if constexpr (std::is_lvalue_reference<T>::value)
    return t;
  else
    return std::move(t);
}

给你输出:

rvalue
lvalue
于 2019-06-21T15:43:59.770 回答