简体   繁体   English

在C ++中正确使用完善的转发?

[英]A proper use of perfect forwarding in C++?

I wonder if the following is a proper use of perfect forwarding in C++ (explanation below): 我想知道以下是否是在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;
};

An object of type A contains a B and a C object. 类型为A的对象包含一个B对象和一个C对象。 It is required that an A object can be constructed from a pair ( B b , C c ) alone. 要求A对象只能由一对( B bC c )构成。 Now the context dictates that it will always be the case that c has to be copied into _c for such a construction. 现在上下文表明,对于这种构造,总是总是必须将c 复制_c中。 Therefore, c is passed as const C& . 因此, c作为const C&传递。 On the other hand, depending on the case, b has to be copied into _b , or it may be possible to move b it into _b . 另一方面,根据情况,必须将b复制到_b ,或者可以将b移到_b Will the above code accomplish this correctly, ie will it generate appropriate constructors depending on the way objects of type A are constructed in the code? 上面的代码能否正确完成此操作,即是否会根据代码中构造A类型对象的方式生成适当的构造函数? Ie, is this a proper use of perfect forwarding? 即,这是对完美转发的正确使用吗?

I think it does the right thing, but the reason why I'm irritated: I think this is somewhat ugly as I only want to call the constructor with lvalues or rvalues of type B in the first argument. 我认为这样做是正确的,但我感到恼火的原因是:我认为这有点难看,因为我只想在第一个参数中使用B型左值或右值调用构造函数。 The above code would - in principle - allow any type T . 上面的代码原则上将允许任何类型T Is the alternative of defining the two methods 是定义两种方法的替代方法

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

to be preferred? 被首选?

Anything that B can be constructed from as one argument will work in your sample code. B可以作为一个参数构造的任何东西都将在您的示例代码中起作用。

And that isn't a bad thing. 那不是一件坏事。

If B has a constructor that takes an int , you can pass an int as the first parameter. 如果B的构造函数采用int ,则可以将int作为第一个参数传递。 Instead of creating a temporary B then moving it into your structure, it will instead directly construct the B in your structure from the int . 与其创建一个临时B而不是将其移到您的结构中,不如从int直接在您的结构中构造B

If you really, really want what you are describing, you can enforce it with three means: 如果您确实想要描述,可以通过三种方式实施它:

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

or 要么

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

which blocks any kind of conversion. 阻止任何类型的转换。 Finally, if B is cheap to move, you can just do: 最后,如果B的价格便宜,您可以执行以下操作:

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

which follows the idiom "if you want speed, pass by value". 这是成语“如果您想要速度,请按值传递”。

Here implicit conversion from the argument to B is blocked as well, unless the caller explicitly converts. 在这里,除非调用者显式转换,否则从参数到B隐式转换也将被阻止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM