如何重载变量构造函数以将自己作为类?

问题描述 投票:6回答:3

我不知道标题是否有意义。我试图重载一个类构造函数,使自己作为参数。但是,模板让我很难过:

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);
}

我已经尝试过做很多事情,但是,我不能为我的生活得到这个编译。我究竟做错了什么?有人请指导我完成这个吗?

c++ templates variadic-templates
3个回答
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
投票

SFINAE救援!

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表达式来检查参数包中的每个类型,以确定我们是否有一组控制器或一组类。请注意,条件是互斥的,允许编译器明确地选择要调用的构造函数给出一组参数。

您是否计划将这些类存储在控制器中(如何?)?他们是否从一个共同的基础继承(如果他们这样做会更容易,如果他们没有这样做的话,那会更容易)?从多个控制器构建控制器有什么作用?控制器是否获得给定控制器的子类?


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")};
© www.soinside.com 2019 - 2024. All rights reserved.