std :: forward如何接收正确的参数? [英] How does std::forward receive the correct argument?

查看:197
本文介绍了std :: forward如何接收正确的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



请考虑:

  void g(int& ; 
void g(int&&);

template< class T>
void f(T& x)
{
g(std :: forward< T>(x));
}

int main()
{
f(10);
}

由于id-expression x 是一个左值, std :: forward 对于左值和右值有重载,为什么调用不会绑定到 std :: forward 需要一个左值吗?

  template< class T& ; 
constexpr T&& forward(std :: remove_reference_t>& t)noexcept;


解决方案

std :: forward 的过载取值为:

  ;类T> 
constexpr T&& forward(remove_reference_t T& t)noexcept;

它与 T == int 绑定。此函数指定返回:

  static_cast<&&>(t)

因为 T f 推导为 int 。因此,这个超载将$ value $ int 转换为xvalue:

  static_cast< int&>(t)

因此调用 g ;&) overload。



总之, std :: forward 可以根据 T 的类型将其参数转换为lvalue或rvalue。



std :: forward 的右值重载只能转换为rvalue。如果你试图调用这个重载并转换为左值,程序是错误的(需要一个编译时错误)。



所以重载1:

  template< class T> 
constexpr T&& forward(remove_reference_t T& t)noexcept;

捕获lvalues。



 模板< class T> constexpr T&& forward(remove_reference_t>& t)noexcept; 

捕获rvalues(xvalues和prvalues)。



重载1可以将其左值参数转换为lvalue或xvalue(后者将被解释为用于重载解析目的的右值)。



重载2可以将其右值参数仅转换为xvalue(将被解释为用于重载解析目的的右值)。



重载2用于标记为B的情况。 rvalue as a rvaluein N2951 。简而言之,此案例支持:

  std :: forward< T>(u.get()); 

您不确定 u.get()返回一个左值或右值,但是如果 T 不是一个左值引用类型,则要移动返回的值。但是你不使用 std :: move ,因为如果 T



我知道这听起来有点麻烦。但是 N2951 遇到了重大问题,无法设置激活用例如何 std :: forward 应该与所显式提供的模板参数的所有组合以及普通参数的隐式提供的表达式类别相一致。 / p>

这不是一个容易阅读,但每个模板和普通参数的组合的原理 std :: forward 位于 N2951 中。



std :: forward 不完全是 N2951 提议的。但是 通过提供的所有六个测试N2951


Consider:

void g(int&);
void g(int&&);

template<class T>
void f(T&& x)
{
    g(std::forward<T>(x));
}

int main()
{
    f(10);
}

Since the id-expression x is an lvalue, and std::forward has overloads for lvalues and rvalues, why doesn't the call bind to the overload of std::forward that takes an lvalue?

template<class T>
constexpr T&& forward(std::remove_reference_t<T>& t) noexcept;

解决方案

It does bind to the overload of std::forward taking an lvalue:

template <class T>
constexpr T&& forward(remove_reference_t<T>& t) noexcept;

It binds with T == int. This function is specified to return:

static_cast<T&&>(t)

Because the T in f deduced to int. So this overload casts the lvalue int to xvalue with:

static_cast<int&&>(t)

Thus calling the g(int&&) overload.

In summary, the lvalue overload of std::forward may cast its argument to either lvalue or rvalue, depending upon the type of T that it is called with.

The rvalue overload of std::forward can only cast to rvalue. If you try to call that overload and cast to lvalue, the program is ill-formed (a compile-time error is required).

So overload 1:

template <class T>
constexpr T&& forward(remove_reference_t<T>& t) noexcept;

catches lvalues.

Overload 2:

template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;

catches rvalues (which is xvalues and prvalues).

Overload 1 can cast its lvalue argument to lvalue or xvalue (the latter which will be interpreted as an rvalue for overload resolution purposes).

Overload 2 can can cast its rvalue argument only to an xvalue (which will be interpreted as an rvalue for overload resolution purposes).

Overload 2 is for the case labeled "B. Should forward an rvalue as an rvalue" in N2951. In a nutshell this case enables:

std::forward<T>(u.get());

where you are unsure if u.get() returns an lvalue or rvalue, but either way if T is not an lvalue reference type, you want to move the returned value. But you don't use std::move because if T is an lvalue reference type, you don't want to move from the return.

I know this sounds a bit contrived. However N2951 went to significant trouble to set up motivating use cases for how std::forward should behave with all combinations of the explicitly supplied template parameter, and the implicitly supplied expression category of the ordinary parameter.

It isn't an easy read, but the rationale for each combination of template and ordinary parameters to std::forward is in N2951. At the time this was controversial on the committee, and not an easy sell.

The final form of std::forward is not exactly what N2951 proposed. However it does pass all six tests presented in N2951.

这篇关于std :: forward如何接收正确的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆