如何在构建 class 期间调用的向量中存储可变参数函数?

How to store variadic functions inside a vector to be called during construction of a class?

我不确定我所问的是否可行,因为我认为我混淆了编译时间和 运行 时间操作。

假设我有一个 class ExClass。这个 class 有 10 行要添加到面板的小部件。在模板实现之前,我会做:

void ExClass::addRow0()
{
  this->addWidget(widget1,row,col); //where row and col are different numbers, ex 0,0
  this->addWidget(widget2,row,col); // 0,1
  this->addWidget(widget3,row,col); // 0,2
  this->addWidget(widget4,row,col); // etc.
}

void ExClass::addRow ... 10(){ ... }

然后我会让 class 的构造函数看起来像这样:

ExClass::ExClass()
{
  addRow0();
  addRow1();
  .
  .
  .
  addRow10();
}

然后我决定在 ExClass 中将可变参数函数作为私有函数,它可以使用任意数量的小部件并像这样自动构建行:

const int MAXCOLSIZE = 2;

template<typename T>
void addToWidget(T* widget,int row,int size)
{
  int col = std::abs(size - MAXCOLSIZE);
  this->addWidget(widget,row,col,Qt::AlignHCenter);
}

template<typename T>
void addRow(int row, T* widget)
{
  this->addWidget(widget,row,MAXCOLSIZE,Qt::AlignHCenter);
}

template<typename Widget, typename... T>
void addRow(int row, Widget *w,T*...t)
{
  constexpr std::size_t n = sizeof...(T);
  addToWidget(w,row,n);
  addRow(row,t...);
}

template<typename T>
void addSingle(int row, T *widget)
{
  this->addWidget(widget,row,0,1,MAXCOLSIZE+1,Qt::AlignVCenter);
}

我这样做的原因是,我不必创建 addRowN 的 10 个函数来在构造函数中调用。然后它会为我节省一些编码和麻烦。但是,它确实使我的构造函数看起来像这样:

ExClass::ExClass()
{
  addRow(0,widget1,widget2,widget3);
  addRow(1,widget4,widget5,widget6);
  addSingle(2,widget7);
  addRow(3,widget8,widget9,widget10);
  .
  .
  .
  addRow(10,widget23,widget24,widget25);
}

现在想想,可读性差很多,在某些地方可能会变得疯狂。所以我可能会恢复到原来的方式并通过我创建的特殊私有向量调用它:

std::vector<std::function<void()>> rowFuncs = {
  std::bind(&ExClass::addRow0,this),
  . 
  .
  .
  std::bind(&ExClass::addRow10,this)
};

但是,在我回到那个之前,我想知道是否有一种方法可以将可变参数函数以相同的方式传递到向量中?我试过了:

std::vector<std::function<void(...)>> rowFuncs;

但是它不喜欢它不知道参数是什么类型而且我无法存储它们。所以我想知道我正在尝试做的事情是否有可能?如果我可以将它分解成一个函数,这样我就可以清理我的构造函数,这样它就不是 10 多行代码,而是一个调用函数向量的函数,就像我对其他实现所做的那样:

void ExClass::buildLayout()
{
  for(const auto& fn : rowFuncs)
    fn();
}

那么我的构造函数将很高兴地看起来像:

ExClass::ExClass()
{
  buildLayout();
}

我有 buildLayout 在原始函数实现中工作。但是我想知道这是否有可能与我的可变参数函数实现有关。如果有人有任何建议,或者如果这是可能的,我将不胜感激!

编辑:我应该提到 ExClass 在这种情况下,有 25 个独特的小部件。 class.

的所有私有成员

遵循@Midren 评论中的建议。我能够实现我想要的。但是,我还需要添加模板定义。这是工作示例:

class ExClass
{
  public:
    ExClass();

    void constructLayout();

  private:

    const int MAXCOLSIZE = 2;

    template<typename T>
    void addToWidget(T* widget,int row,int size)
    {
      int col = std::abs(size - MAXCOLSIZE);
      this->addWidget(widget,row,col,Qt::AlignHCenter);
    }

    template<typename T>
    void addRow(int row, T* widget)
    {
      this->addWidget(widget,row,MAXCOLSIZE,Qt::AlignHCenter);
    }

    template<typename Widget, typename... T>
    void addRow(int row, Widget *w,T*...t)
    {
      constexpr std::size_t n = sizeof...(T);
      addToWidget(w,row,n);
      addRow(row,t...);
    }

    template<typename T>
    void addSingle(int row, T *widget)
    {
      this->addWidget(widget,row,0,1,MAXCOLSIZE+1,Qt::AlignVCenter);
    }

    Widget *widget1 = new Widget();
    Widget *widget2 = new Widget();
    Widget *widget3 = new Widget();
    Widget *widget4 = new Widget();

    std::vector<std::function<void()>> rowFuncs = {
      std::bind(&ExClass::addRow<Widget,Widget>,this,0,widget1,widget2),
      std::bind(&ExClass::addSingle<Widget>,this,1,widget3),
      std::bind(&ExClass::addSingle<Widget>,this,1,widget4)
    };
};

然后您可以像这样构建布局:

void ExClass::constructLayout()
{
  for(const auto& fn : rowFuncs)
    fn();
}