你能完美地转发C++23中的表达式吗?

Jan*_*tke 3 c++ language-lawyer perfect-forwarding c++23

auto()在 C++23 中,由于or ,完美转发纯右值变得更加容易auto{}。有了这个新工具,现在是否可以为具有以下要求的FORWARD(e)表达式构建表达式?e

  1. FORWARD(e)与 具有相同的类型e,忽略引用限定符
  2. ifdecltype(e)是左值/右值引用,则FORWARD(e)分别是左值/x值
  3. 否则,FORWARD(e)具有相同的值类别e
  4. 不得进行额外的复制或移动

我们已经可以进行不完美转发了std::forward

#define FORWARD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

这会保留类型并适当地转换引用。但是,纯右值将转换为 xvalue,因为std::forward返回右值引用(即FORWARD(e)转换后是 xvalue)。

作为结果:

T x = T();          // copy elision because x is initialized to prvalue
T x = FORWARD(T()); // calls move constructor
Run Code Online (Sandbox Code Playgroud)

是否有可能在 C++ 中进行真正的完美转发,包括保留纯右值?

Art*_*yer 5

您基本上想要FORWARD(e)成为e,除非e碰巧命名了一个右值引用变量,在这种情况下您想要成为move(e)

您可以简单地转换为 的类型decltype((e))(如果e是纯右值,则将被省略),除非e是右值引用变量,因为decltype((e))将是左值引用。

#include <type_traits>

template<typename IdType, typename ExprType>
using perfect_forward_cast = std::conditional_t<std::is_rvalue_reference_v<IdType>,
    IdType,
    ExprType
>;

#define FORWARD(...) ::perfect_forward_cast<decltype( __VA_ARGS__ ), decltype(( __VA_ARGS__ ))>( __VA_ARGS__ )
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/WYehMxzPb