c++ - 如何将 `void(*fn)(const char *, ...)` 转换为 `std::function`,反之亦然

标签 c++ function lambda variadic-functions

typedef void(*fn1)(const char *, ...);
typedef std::function<void(const char *, ...)> fn2; // has initializer but incomplete type

直觉上,这些对我来说实际上是一样的,但显然我的直觉让我失望了。我将如何协调这些数据类型?

  1. fn2 为什么是不完整的类型?
  2. 需要对 fn2 的签名进行哪些更改,以允许我为其分配 fn1 类型?
  3. 创建要分配给 fn2 的 lambda 时,如何访问可变参数列表?

    换句话说,等价于以下的 lambda 是什么?

    void fn1_compatible (const char * format, ...) {
      va_list args;
      va_start(args, format);
      //TODO: Do stuff with variadic arguments
      va_end(args);
    }
    

NOTE: As an aside, these signatures are related to logging, but please answer the question in a general (not logging) context.

最佳答案

std::function 不支持可变函数. std::function 采用一种类型,它看起来像这样:

template<class>
class function;  // Intentionally incomplete

template<class Ret, class... Args>
class function<Ret(Args...)> {
    // Deduce return type and argument types from function type
};

但这并不能推导出可变参数函数的类型。所以void(const char*)会工作( RetvoidArgs...const char* ),但是 void(const char*, ...)不会工作(因为这需要从 Ret(Args..., ...) 中推导出来)

要从中创建一个仿函数对象,要么只使用一个裸函数指针,就像您对 fn1 所做的那样, 或者凑合 C 标准库对 vprintf 等函数所做的事情:

decltype(auto) my_variadic_function(const char * format, ...) {
  va_list args;
  va_start(args, format);
  try {
      auto&& return_value = vmy_variadic_function(format, args);
  } catch (...) {
      va_end(args);
      throw;
  }
  va_end(args);
  return std::forward<decltype(return_value)>(return_value);
}

void vmy_variadic_function(const char* format, va_list args) {
    // Do stuff with args
}

然后通过vmy_variadic_functionstd::function<void(const char*, va_list)> .

关于c++ - 如何将 `void(*fn)(const char *, ...)` 转换为 `std::function`,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55423225/

相关文章:

C++ ifstream 和 "umlauts"

c++ - 什么时候应该在 C++ 中使用 "this"关键字?

python - 在多个模块中使用函数类型的错误签名错误

java - java会允许使用功能接口(interface)作为方法吗?

具有宽松类型要求的 C++17 lambda 捕获

c++ - 在类内部分配函数指针

c++ - 使用 assign() 是初始化我的 C++ 结构 vector 的好方法吗?

function - 定义具有三个变量的分段函数

javascript - 如果我调用一个参数比定义接受的参数多的函数,会发生什么情况?

c# - 使用 2 个字段对 C# 进行列表排序