std::foward 的第二次重载(cppreference.com 上的示例)
Second overload of std::foward (example on cppreference.com)
我知道 std::forward
的第二个重载:
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
用于右值(如 Howard Hinnant 在他的回答中所述:)
有一个在 cppreference.com 处使用此重载的示例(Praetorian 在 中也提到了):
- 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()));
仍然,我无法理解为什么有人需要添加外前锋。
编辑: 编辑移至后续问题:
Why is the outer forward forward<decltype(forward<T>(arg).get())>
even needed?
It's not. The expression already is of its own correct value category. In C++17 (when returning by value bigger types) it's even a pessimization. All it does is turn a potential prvalue into an xvalue, 。我很想说这是货物崇拜编程。
我知道 std::forward
的第二个重载:
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
用于右值(如 Howard Hinnant 在他的回答中所述:
有一个在 cppreference.com 处使用此重载的示例(Praetorian 在
- 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()));
仍然,我无法理解为什么有人需要添加外前锋。
编辑: 编辑移至后续问题:
Why is the outer forward
forward<decltype(forward<T>(arg).get())>
even needed?
It's not. The expression already is of its own correct value category. In C++17 (when returning by value bigger types) it's even a pessimization. All it does is turn a potential prvalue into an xvalue,