[英]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 b
, C 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.