c++ - std::foward 的第二次重载(cppreference.com 上的示例)

标签 c++ c++11 perfect-forwarding

我知道 std::forward 的第二次重载:

template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
用于右值(如 Howard Hinnant 在他的回答中所述: How does std::forward receive the correct argument? )
cppreference.com 处有一个何时使用此重载的示例(Praetorian 在 How does std::forward receive the correct argument? 中也提到了这一点):
  1. Forwards rvalues as rvalues and prohibits forwarding of rvalues as lvalues This overload makes it possible to forward a result of an expression (such as function call), which may be rvalue or lvalue, as the original value category of a forwarding reference argument.

For example, if a wrapper does not just forward its argument, but calls a member function on the argument, and forwards its result:

// transforming wrapper 
template<class T>
void wrapper(T&& arg)
{
    foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
}

where the type of arg may be

struct Arg
{
    int i = 1;
    int  get() && { return i; } // call to this overload is rvalue
    int& get() &  { return i; } // call to this overload is lvalue
};

我真的不明白这个例子。为什么是外向前forward<decltype(forward<T>(arg).get())>甚至需要?
Cppreference 指出:

This overload makes it possible to forward a result of an expression (such as function call), which may be rvalue or lvalue, as the original value category of a forwarding reference argument.


举个例子:
void func(int& lvalue)
{
    std::cout << "I got an lvalue!" << std::endl;
}

void func(int&& rvalue)
{
    std::cout << "I got an rvalue!" << std::endl;
}

template <typename T>
T&& myForward(typename std::remove_reference_t<T>& t)
{
    return static_cast<T&&>(t);
}

struct foo
{
    int i = 42;
    int& get()& { return i; }
    int get()&& { return i; }
};

template <typename T>
void wrapper(T&& t)
{

    func(myForward<T>(t).get());
}

int main()
{
    foo f;
    wrapper(f);
    wrapper(foo());

    return 0;
}
这打印:
I got an lvalue!
I got an rvalue!
很好,没有外部转发,同时它还转发“表达式的结果 [...] 作为转发引用参数的原始值类别。”它甚至不需要 std::forward 的第二次重载.只有在调用 func() 时才需要此重载像这样:
func(myForward<decltype(myForward<T>(t).get())>(myForward<T>(t).get()));
尽管如此,我还是无法理解为什么有人需要添加外部前锋。
编辑:编辑移至后续问题:RValue-reference overload of std::forward potentially causing dangling reference?

最佳答案

Why is the outer forward forward<decltype(forward<T>(arg).get())> even needed?


It's not .该表达式已经属于它自己的正确值类别。在 C++17 中(当按值返回更大的类型时)它甚至是一种悲观化。它所做的只是将潜在的纯右值转换为 xvalue,and inhibiting copy elision .我很想说这是 cargo 崇拜编程。

关于c++ - std::foward 的第二次重载(cppreference.com 上的示例),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41543571/

相关文章:

c++ - 绑定(bind)到本地引用的对象是否会自动销毁?

c++ - 使用值初始化数组对数据进行零初始化

c++ - 如何在 lambda 函数中保留对捕获的智能指针的引用?

c++ - 将可变模板参数传递给可变函数

c++ - 在 C++ 中索引离开数组边界后发生段错误

c++ - fstream 正在向我的文件的每一行添加字符?

c++ - makefile - 依赖的依赖

C++ shared_ptr use_count for nullptr

c++ - 无法理解为什么完美转发不起作用

c++ - 将一组转发引用包装在一个元组中