C++中完美转发的正确使用
A proper use of perfect forwarding in C++?
我想知道以下是否是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&
。另一方面,根据情况,必须将b
复制到_b
,或者可以将b
移动到_b
。上面的代码会正确地实现这一点吗?也就是说,它会根据代码中构造A
类型对象的方式生成适当的构造函数吗?也就是说,这是完美转发的正确使用吗?
我认为它做了正确的事情,但我生气的原因是:我认为这有点难看,因为我只想在第一个参数中调用具有B
类型的lvalues或rvalues的构造函数。上述代码原则上允许任何类型的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
作为第一个参数。它将直接从int
构造结构中的B
,而不是创建临时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
的隐式转换也被阻止,除非调用者显式转换。
相关文章:
- 将函数参数完美转发到函数指针:按值传递呢?
- C++20理念:要求表达和完美转发
- 我可以列表初始化 std::vector 并完美转发元素吗?
- 返回值的完美转发?
- 使用衰减与完美转发
- 可变参数模板:将整数参数完美转发到 lambda
- 完美转发C++重载和模板化函子及其参数
- 在完美转发中需要衰减
- C++完美转发:如何避免悬空引用
- 无法理解一段具有完美转发和省略号的C++代码
- 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?
- 完美转发可变参数模板模板
- 在完美转发函数中公开参数类型,避免代码重复
- 使用完美转发的模板转换构造函数
- 完美转发使用结构化绑定声明的变量
- 完美转发常量参数以进行持续评估
- 使用auto&&完美转发返回值
- 完美转发可变参数模板参数到成员函数
- 无需使用 ODR 即可实现完美转发
- 使用模板类完美转发