如何重载可变参数的构造函数以使其自己为类?

时间:2019-04-29 21:49:05

标签: c++ templates variadic-templates

我不知道标题是否有意义。我试图重载一个类构造函数以将其自身作为参数。但是,模板给我带来了麻烦:

class Controller
{
  public:
  template<typename...Classes>
  Controller(Classes&...classes)
  {
    // Do stuff with classes
  }

  template<Controller&...Controllers, typename Classes>
  Controller(Controllers...controllers(Classses&...classes)) : Controller(Classes&...classes){} 
  ^ This is where I am having my problem
};

我基本上正在尝试执行以下操作:

int main()
{
  ClassA A;
  ClassB B;
  ClassC C;
  ClassD D;

  Controller controller1(A,B);
  Controller controller2(C,D);

  Controller controllerOtherControllers(controller1,controller2);
}

我已经尝试做很多事情,但是,我一生无法将其编译。我究竟做错了什么?有人可以带我过去吗?

3 个答案:

答案 0 :(得分:2)

构造函数是简单的部分,有趣的部分是您希望如何存储对象。不可能只写Classes... classes来存储。

  • 实际上与第一个相同:Controller ``controllerOtherControllers(controller1,controller2);会称呼 第一个使用Classes... = Controller<A, B>, Controller<C, D>
  • 的构造函数
  • 成为一个解开的人,即不用将Controller<Controller<A, B>, Controller<C, D>>展平为Contrtoller<A, B, C, D>

第二种方法将需要一个模板,但是我不确定在这种情况下是否可以嵌套2个变量。

此外,请注意,您正在尝试通过Controller类来复制std::tuple

您必须决定的事情是是否要展平效果以及是否/如何存储构造函数中使用的对象。

答案 1 :(得分:1)

向救援求救!

class Controller
{
  public:
  // this will not be called for controllers
  template<typename... Classes, typename = std::enable_if_t<
    !(std::is_same<std::remove_cv_t<Classes>, Controller> && ...)
  >>
  Controller(Classes &... classes) {
    // ...
  }

  // this will be called for controllers
  template<typename... Controllers, typename = std::enable_if_t<
    (std::is_same<std::remove_cv_t<Controllers>, Controller> && ...)
  >>
  Controller(Controllers &... controllers) {
    // ...
  }
};

这使用fold表达式来检查参数包中的每种类型,以确定我们是否有一组控制器或一组类。请注意,条件是互斥的,这使编译器可以明确选择要调用的构造函数以提供一组参数。

您是否打算将这些类存储在控制器中(如何?)?它们是从一个共同的基础继承吗(如果这样做,会更容易,但如果不是,那会更容易)?从多个控制器构造一个控制器有什么作用?控制器是否获得给定控制器的子类?

答案 2 :(得分:0)

最简单的方法可能是编写一个构造器,该构造器采用一个控制器的初始化列表:

class Controller {
    std::vector<Controller> sub_controllers; 
    std::string name;
   public:
    // Default constructor
    Controller() = default;
    // Construct it by name
    Controller(std::string const& name) 
      : name(name) 
    {}

    // This allows you to just directly pass a list in brackets
    Controller(std::initializer_list<Controller> list) 
      : sub_controllers(list) 
    {}
};

现在,您可以创建一个包含其他控制器列表的控制器:

Controller myController{Controller("Joe"), Controller("Bob"), Controller("Smith")};