c++ - C++ 中完美转发的正确使用?

标签 c++ perfect-forwarding

我想知道以下是否是 C++ 中完美转发的正确使用(解释如下):

class A
{
  public:

  //...
  template <typename T> A( T&& b,const C& c ) : _b{ std::forward<T>( b ) },_c{ c } { }
  //...

  private:

  B _b;
  C _c;
};

A 类型的对象包含 B和一个 C目的。需要 A对象可以单独由一对( B bC c )构造。现在,上下文表明情况总是如此 c必须复制_c对于这样的 build 。因此,c传递为 const C& 。另一方面,根据情况,b必须复制到 _b ,或者可以移动b进入 _b 。上面的代码是否可以正确完成此操作,即它是否会根据 A 类型的对象的方式生成适当的构造函数是在代码中构建的吗?即,这是完美转发的正确使用吗?

我认为它做了正确的事情,但我生气的原因是:我认为这有点难看,因为我只想使用 B 类型的左值或右值调用构造函数。在第一个参数中。原则上,上面的代码允许任何类型 T 。是定义两个方法的替代方案

A( B& b,const C& c ) : _b{ b },_c{ c } { }
A( B&& b,const C& c ) : _b{ std::move( b ) },_c{ c } { }

成为首选?

最佳答案

任何可以作为一个参数构造的 B 都可以在您的示例代码中使用。

这并不是一件坏事。

如果 B 具有采用 int 的构造函数,则可以传递 int 作为第一个参数。它不会创建临时 B 然后将其移动到您的结构中,而是直接从 int 在您的结构中构造 B

如果您真的非常想要您所描述的内容,您可以通过三种方式来实现它:

// copy:
A( B const& b,const C& c ) : _b{ b },_c{ c } { }
// move:
A( B&& b,const C& c ) : _b{ std::move( b ) },_c{ c } { }

template <typename T, typename=std::enable_if<
  std::is_same<
    typename std::decay<T>::type,
    B
  >::value
>::type> A( T&& b,const C& c ) : _b{ std::forward<T>( b ) },_c{ c } { }

它会阻止任何类型的转换。最后,如果 B 移动成本低廉,您可以这样做:

A( B b, const C& c ): _b(std::move(b)), _c(std::move(c)) {}

这遵循了“如果你想要速度,就按值(value)传递”这一成语。

此处从参数到 B 的隐式转换也会被阻止,除非调用者显式转换。

关于c++ - C++ 中完美转发的正确使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26488879/

相关文章:

c++ - 因为 std::swap(s1, s2) 就足够了,所以 string::swap 可以忽略吗?

c++ - 字符串与十六进制值的用户定义文字

c++ - 为哈希表初始化 STL 列表的动态数组(单独链接)

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

c++ - 将参数转发给 lambda 以供后续异步调用

c++ - 按值传递和 move ,或两种方法

c++ - QT_NO_CONTEXTMENU 何时定义?

c++ - 是否可以同时在两个对象上使用插入运算符?

c++ - 为什么不使用 `make_x()` 函数尽可能省略 move 构造函数?

c++ - 使用 auto&& 完美转发返回值