【问题标题】:Forwarding all constructors in C++0x转发 C++0x 中的所有构造函数
【发布时间】:2011-03-08 09:20:46
【问题描述】:

在 C++0x 中转发所有父级构造函数的正确方法是什么?

我一直在这样做:

class X: public Super {
    template<typename... Args>
        X(Args&&... args): Super(args...) {}
};

【问题讨论】:

  • 是否有理由反对键入所有构造函数而不是使用模板快捷方式?
  • 是的,时间,如果超级类更新,那么他将陷入混乱的维护之中。自动化解决方案具有无限优势。
  • @DeadMG - 不是真的。那么如果基础得到一个新的构造函数呢?除非需要新信息,否则派生不需要使用它。在这一点上,这个自动化的“解决方案”只是自动将处理这个问题推给派生的所有客户。这通常是完全错误的做法。 Derived 不应该更新,除非有一些对象需要它,并且应该明确地完成,以便通过查看其构造函数来构建对象是显而易见的。为可变参数条件保留可变参数模板。
  • @Thomas - 我发现了类似的用途,所以我想有一些稍微不同的问题最好通过这种结构来解决。在我的情况下,我想要一个通用的“持有人”类,它可以包含任何类型,即使它不是默认可构造的。因此,持有者本身必须接受与其持有的相同的论点,这实际上只能以这种方式解决。
  • @Noah:调用 X 的构造函数是一个可变参数条件 - 你想用 Super 的任何构造函数构造 X,因为 X 不想知道。如果 base 得到一个新的构造函数,Derived 可以自动使用它,而不必为新的 Super 手动更改所有代码。

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


【解决方案1】:

C++0x 中有一个更好的方法

class X: public Super {
  using Super::Super;
};

如果您声明一个完美转发模板,您的类型将在重载解析中表现不佳。想象一下,您的基类可以从 int 转换,并且有两个函数可以打印出类

class Base {
public:
  Base(int n);
};

class Specific: public Base {
public:
  template<typename... Args>
    Specific(Args&&... args);
};

void printOut(Specific const& b);
void printOut(std::string const& s);

你用

来称呼它
printOut("hello");

会叫什么?这是模棱两可的,因为Specific 可以转换任何参数,包括字符数组。它这样做不考虑现有的基类构造函数。使用 using 声明继承构造函数仅声明完成此工作所需的构造函数。

【讨论】:

  • 我只是想知道 explicit 关键字是否不会使呼叫明确,同时允许完美的转发模板工作。并不是说我会推荐自动生成派生构造函数...
  • 是否可以避免这种歧义,为构造函数添加一个默认的额外参数(好吧,也许忘记 variadic 转发:P)和 disable_if 条件,基于 B 的可构造性推导出来的论点?
  • 这个using Super::Super 解决方案的名称是什么?它似乎不在 GCC 4.5 中。
  • @user643722:它被称为“继承构造函数”,没有人实现它。不是 GCC 4.7,即使在主干中也不是 Clang,不是 VC11,nobody
  • 请注意,这个功能现在终于在 gcc 4.8 中可用了。
【解决方案2】:

认为如果你想正确转发事情,你需要做Super(std::forward&lt;Args&gt;(args)...)args 有一个名字,所以我相信它会在右值引用之前绑定到常规引用。

更重要的是,您不会以这种方式转发复制构造函数。编译器仍会为您生成一个,因为它不考虑模板构造函数。在提供的示例中,您没问题,因为编译器生成的无论如何都会调用父复制构造函数,这正是您想要的。如果这在更复杂的情况下不合适,那么您必须自己编写。

【讨论】:

  • Super(std::forward&lt;Args&gt;(args)...) 是正确的,所以你非常接近。请记住,转发需要明确的模板参数。
  • 我本来就有这个,后来我自己猜到了。谢谢指正。
  • 这很棒。您对 std::forward 的作用有直觉吗? (它是一阶的吗?)为什么我们不能只写“args ...”?这会导致调用复制构造函数吗?
  • 因为如果它们中的任何一个是右值引用(并且您调用的构造函数期望这样),那么尝试传递它们会导致问题,因为它们现在是左值引用(它们有名称)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
相关资源
最近更新 更多