我想知道以下是否是 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
对于这样的 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/