【问题标题】:A proper use of perfect forwarding in C++?在 C++ 中正确使用完美转发?
【发布时间】:2014-10-21 14:13:24
【问题描述】:

我想知道以下是否是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 b,C c) 构造。现在上下文表明,对于这样的构造,c 必须复制_c 中。因此,c 作为const C&amp; 传递。另一方面,根据具体情况,必须将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 } { }

是首选?

【问题讨论】:

  • 是的,没错。如果你不喜欢它,定义两个构造函数。

标签: c++ perfect-forwarding


【解决方案1】:

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)) {}

遵循成语“如果您想要速度,请按值传递”。

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

【讨论】:

    猜你喜欢
    • 2011-04-05
    • 2022-01-22
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 2012-06-23
    相关资源
    最近更新 更多