主要思路是使用std::forward_as_tuple将参数包保存到元组中,然后利用std::apply遍历元组中的数据
这里需要用到auto类型推断,如果参数中有自定义类型还需要注册元对象系统
最后在apply中使用折叠表达式展开参数包(xxxx(args), …)并逐一处理
// consider to use exception?
template<typename... Args>
void transaction(
const QString& queryStat,
std::function<void(QSqlQuery&)> process = std::function<void(QSqlQuery&)>(),
Args&&... args
) const {
QSqlQuery query(m_db);
query.prepare(queryStat);
auto argTuple = std::forward_as_tuple(args...);
std::apply([&query, this](auto&&... args) {
((query.addBindValue(QVariant::fromValue(args)), std::cout << args), ...);
}, argTuple);
query.exec();
// qDebug() << (
// query.lastError().text().isEmpty()?
// _query + "succeed":
// query.lastError().text()
// );
if(query.lastError().text().isEmpty()) {
qDebug() << "[SQL TRANSACTION] " + queryStat + " succeed";
while(query.next()) {
process(query); // query.value(index).toAnyDataFormat
}
return;
} else {
qDebug() << query.lastError().text();
return;
}
}
以 下 部 分 无 效 , 仅 供 参 考 \color{red}{以下部分无效,仅供参考} 以下部分无效,仅供参考
单元测试
class Test {
public:
Test() = default;
explicit Test(int a):m_a(a) {}
friend const std::ostream& operator<< (
std::ostream &os,
const Test &t
) {
(void)t.m_a;
return os << "test";
}
private:
int m_a = 0;
};
Q_DECLARE_METATYPE(Test)
void TestCompileArglistQuery() {
auto f =3;
QVariant d;
qDebug() << d.fromValue(f);
qDebug() << d;
ORMHelper().prepare("UPDATE USER", 0, 2, Test(0), 4, 5);
}
执行结果
QVariant(int, 3)
QVariant(Invalid)
02test45
failed