【问题标题】:Forward constructors to a member object将构造函数转发给成员对象
【发布时间】:2014-01-12 03:14:36
【问题描述】:

这是将所有构造函数转发到成员数据结构的好方法吗?

template<typename VectorData>
class VectorFunctionality
{
    VectorData data;
public:
    VectorFunctionality() = default;
    VectorFunctionality(const VectorFunctionality&) = default;
    template<typename ...Args>
    VectorFunctionality(Args... args) : data(std::forward<Args>(args)...) {};
};

VectorData 可以是 std::array、std::vector 等。 VectorFunctionality 继承了所有的 VectorData c'tors。 这有助于避免在 VectorFunctionality 中写入许多 c'tors,其他用于 std::array 和其他用于 std::vector。

【问题讨论】:

  • 如果编译器支持 C++11 的构造函数继承,也许只使用private 继承,在构造函数中继承。免责声明:我还没有尝试过。
  • 如果你这样不小心写了,那么std::is_constructible&lt;VectorFunctionality, Args...&gt;::value对于Args...任何选择都是正确的,这可能是不可取的。
  • 也使用VectorFunctionality(Args&amp;&amp;... args) 隐式转发参数。在一般情况下,我不认为这提供了一个好的和简单的 API。用户不会轻易理解构造函数的使用,除非你有一个很好的文档

标签: c++ templates c++11 constructor


【解决方案1】:

你必须小心一点,因为可变参数构造函数可能会无意中匹配你不想要的东西。

获取以下(未经测试的)代码:

VectorFunctionality<int> vf1;
VectorFunctionality<int> vf2(vf1); // Unintentionally calls the templated constructor

给定对 VectorFunctionality 的非常量引用,可变参数构造函数是更好的匹配,因为它不需要非常量到 const 的转换,因此调用它而不是复制构造函数。

解决这个特定问题的一种方法是添加另一个构造函数,如下所示:

VectorFunctionality(VectorFunctionality& that) : VectorFunctionality(static_cast<VectorFunctionality const&>(that)) {}

注意:此问题还有其他表现形式(例如,如果您有一个派生自 VectorFunctionality 的实例怎么办?)。

【讨论】:

  • 复制构造永远不会与构造函数模板匹配:上面的代码将调用 [defaulted] 复制构造函数。即使它会调用模板构造函数,它实际上也会做正确的事情,即将调用转发给成员。
  • 不带派生到基础转换的直接引用绑定是精确匹配,cv-qualification 无关紧要。它仅与比较两个参考绑定有关,而 OP 的 ctor 模板则不然。在这里,我们有两个精确匹配,但一个模板和一个非模板,因此选择了非模板。
  • @DietmarKühl “复制构造永远不会与构造函数模板匹配”我不确定。 ctor 模板从不被视为复制或移动 ctor,但可以通过重载决议选择它,作为比采用const&amp; AFAIK 的惯用复制ctor 更好的匹配。这需要两者都参考。 Live example
  • 您可以使用const_cast 代替static_cast
  • @DyP:很有趣。我一直认为你不能用模板构造函数劫持复制构造。看起来,模板构造函数不会阻止编译器创建自己的版本,但这并不意味着复制构造函数总是用于复制!非常感谢您指出这一点!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多