Я не уверен, что то, что я спрашиваю, возможно, так как я думаю, что смешиваю время компиляции и время выполнения.
Скажем, у меня есть класс ExClass
. И этот класс имеет 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(){ ... }
Затем конструктор класса выглядел бы так:
ExClass::ExClass()
{
addRow0();
addRow1();
.
.
.
addRow10();
}
Затем я решил сделать функции variadi c как частные функции в 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);
}
Причина, по которой я сделал это таким образом, заключается в том, что мне не пришлось бы создавать 10 функций addRowN
для вызова в конструкторе. Тогда это сэкономит мне немного кода и хлопот. Тем не менее, это сделало мой конструктор похожим на это:
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)
};
Однако, прежде чем я go вернусь к этому, мне было интересно, есть ли способ, которым я может передать мою функцию variadi c в вектор таким же образом? Я попробовал:
std::vector<std::function<void(...)>> rowFuncs;
Однако мне не нравится, что он не знает, какого типа параметры, и я не могу их сохранить. Поэтому мне интересно, возможно ли то, что я пытаюсь сделать? Было бы замечательно, если бы я мог разбить его на функцию, чтобы я мог очистить свой конструктор, чтобы это было не 10+ строк кода, а функция, которая вызывает вектор функций, которые будут вызываться, как я делал с другой реализацией:
void ExClass::buildLayout()
{
for(const auto& fn : rowFuncs)
fn();
}
тогда мой конструктор будет радостно выглядеть так:
ExClass::ExClass()
{
buildLayout();
}
У меня buildLayout
работает в исходной реализации функции. Однако я хотел бы знать, возможно ли это сделать с моей реализацией функции variadi c. Если у кого-то есть какие-либо предложения или если это вообще возможно, я был бы признателен за это!
РЕДАКТИРОВАТЬ: я должен отметить, что ExClass
в этом случае имеет 25 уникальных виджетов. Все частные члены класса.