c++ - 在 C++ 中,是否可以定义一个具有不同代码块的函数,以通过另一个函数执行和传递?

标签 c++ c++11

我有一个处理 SQL 查询的类(它使用 Qt 函数,但我认为这无关紧要)。所有写入数据的查询都具有完全相同的基本框架,如下所示:

bool Database::someSqlFunction(some variables)
{
    if (! startTransaction()) {
        return false;
    }

    QSqlQuery query(m_db);

    try {
        ... Code using the passed variables and query ...
        commitTransaction();
    } catch (...) {
        rollbackTransaction(query);
        return false;
    }

    return true;
}

是否可以重新使用此代码,以便不必为每个函数定义它?我考虑过使用一个函数来调用,该函数带有指向包含不同代码的函数的指针,但是每个函数的签名都不同,因此我必须为每种情况定义一个重载的函数;我也考虑过使用预处理器来生成函数,但是不同数量和类型的参数也是同样的问题。

可以将要执行的代码块传递给另一个函数吗?还是可以通过函数模板完成?

编辑:这是如何实现的:

在标题中:

template<typename SqlFunction>
bool writeHelper(SqlFunction sqlFunction)
{
    if (! startTransaction()) {
        return false;
    }

    QSqlQuery query(m_db);

    try {
        sqlFunction(query);
        commitTransaction();
    } catch (...) {
        rollbackTransaction(query);
        return false;
    }

    return true;
}

以及使用它的示例函数:

bool Database::registerPlayers(const QString &name, int markerId)
{
    return writeHelper([&](QSqlQuery &query) {
        queryPrepare(query, QStringLiteral("INSERT INTO players(id, name, marker) "
                                           "VALUES(NULL, ?, ?)"));
        query.bindValue(0, name);
        query.bindValue(1, markerId != 0 ? markerId : SQLITE_NULL);
        queryExec(query);
    });
}

编辑 2:没有模板也可以实现同样的效果:

使用 std::function,可以简单地传递实际函数中定义的 lambda,而无需使用模板。辅助函数的实现如下所示:

bool Database::writeHelper(std::function<void(QSqlQuery &query)> sqlFunction)
{
    if (! startTransaction()) {
        return false;
    }

    QSqlQuery query(m_db);
    try {
        sqlFunction(query);
        commitTransaction();
    } catch (...) {
        rollbackTransaction(query);
        return false;
    }

    return true;
}

无论如何,使用模板方法显然更好,因为在这种情况下,编译器将在构建时生成所需的函数并可以进行优化,而他不知道使用 std::function 实际会做什么方法,因为调用发生在运行时。

最佳答案

Lambda 闭包似乎正是您所需要的。
https://en.cppreference.com/w/cpp/language/lambda

例如,通用算法与您的用例非常相似:一个常见的 不会改变的算法和一些小部分 可以在调用时自由提供。
https://en.cppreference.com/w/cpp/header/algorithm

在不知道预期的确切细节的情况下, 我在这里提供一个简单的例子:

#include <iostream>

template<typename Fnct>
void
common_part(Fnct fnct)
{
  std::cout << "begin common part\n";
  for(auto i=0; i<3; ++i)
  {
    std::cout << "iteration " << i << " of common part\n";
    fnct(i);
  }
  std::cout << "end common part\n";
}

void
specific_function_A()
{
  common_part(
    [&](const auto &n)
    {
      std::cout << "specific part A: " << n << '\n';
    });
}

void
specific_function_B(int something_else)
{
  common_part(
    [&](const auto &n)
    {
      std::cout << "specific part B: " << n+something_else << '\n';
      something_else*=2;
    });
}

int
main()
{
  specific_function_A();
  std::cout << "~~~~~~~~\n";
  specific_function_B(100);
  return 0;
}

即使 lambda 闭包的签名始终相同, 捕获可以被视为提供额外参数的解决方法。

关于c++ - 在 C++ 中,是否可以定义一个具有不同代码块的函数,以通过另一个函数执行和传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59125822/

相关文章:

c++ - 使用 C++ 模板魔法进行通用和存在量化

c++ - "Template argument for template template parameter must be a class template or type alias template"

具有 1 个参数的 C++ 默认模板化构造函数

c++ - 所有权应该在 STL 容器调用其值的析构函数之前还是之后结束?

c++ - C++ 中的变量到底是什么?

c++ - 进程间通信 - 二进制数据/序列化对象

c++ - 为什么这不会将运算符重载标记为内联导致重复定义错误?

c++ - C++ 标准是否要求无符号整数的最大值为 2^N-1 形式?

c++ - C++-通过在* this指针上使用new放置引起的内存泄漏?

c++ - C++ 中不同数据类型的二元运算符重载