std::函数是否可以用于存储带有可变参数的函数

Can std::function be used to store a function with variadic arguments

本文关键字:函数 变参 参数 用于 是否 std 存储      更新时间:2023-10-16

我在应用程序中传递了一个结构,其中包含一组回调函数:

typedef struct {
    std::function<void (void)>    f1;
    std::function<void (int)>     f2;
    std::function<int  (float *)> f3;
    // ... and so on
} CallbackTable;

根据当前系统状态,我通过将不同的函数绑定到各种回调来处理应用程序中的状态控制;它运行良好。

我现在想做的是添加几个额外的回调,其中签名包含可变数量的参数,类似于printf:例如,

    std::function<int  (const char * format, ...)> printToStdOut;

这个不起作用。在Visual C++中,我收到一条错误消息,上面写着:

error C2027: use of undefined type 'std::_Get_function_impl<_Fty>'

我仍在摸索C++语法的这一领域,如果能给我一些建议,我将不胜感激。我的首要目标是能够拨打以下电话:

myCallbackTable.printToStdOut("I've just eaten %d bananasrn", nBananas);

并根据系统状态将输出定向到控制台、文件或GUI窗口。

编辑:原始答案是错误的,经过修改,但仍然可能不是一个好答案,将其留在这里用于教育目的:

许多可变参数函数都有一个va_list版本。例如CCD_ 1具有CCD_。这些变体显式地采用va_list而不是省略号。

#include <iostream>
#include <functional>
#include <cstdarg>

int main()
{
   std::function<int(const char*,va_list)> test2(vprintf);
   return 0;
}

然而,援引它是一种痛苦。

int invoke_variadic(const std::function<int(const char*,va_list)>& ref,const char* a ,...)
{
    va_list args;
    va_start(args,a);
    ref(a,args);
    va_end(args);
}

原来的帖子有什么问题(谢谢/u/T.C.):std::function<int(const char*,va_list)> test2(printf)编译,我认为这意味着它"有效"。然而,它之所以编译,是因为printf可以接受任何类型的参数(包括va_list),而std::function只检查是否可以用这种方式调用它。

根据@MadScienceDreams的建议,这对我来说效果相当好…

首先,我在结构中定义了std::函数对象的可变参数版本,然后利用这是C++而不是C的事实添加了一些方法:

typedef struct {
    std::function<void (void)>    f1;
    std::function<void (int)>     f2;
    std::function<int  (float *)> f3;
    // ... and so on
    std::function<int  (const char * format, va_list args)> vprintToStdOut; 
    std::function<int  (const char * format, va_list args)> vprintToStdErr;
    int printToStdOut(const char * format, ...)
    {
        va_list ap;
        va_start(ap, format);
        int count = vprintToStdOut(format, ap);
        va_end(ap);
        return count;
    }
    int printToStdErr(const char * format, ...)
    {
        va_list ap;
        va_start(ap, format);
        int count = vprintToStdErr(format, ap);
        va_end(ap);
        return count;
    }
} CallbackTable;

控制台输出的变量参数函数的默认实现是:

myCallbackTable.vprintToStdOut = std::bind(vfprintf, stdout, _1, _2);
myCallbackTable.vprintToStdErr = std::bind(vfprintf, stderr, _1, _2);

从这一点来看,我可以使用我希望使用的语法:

myCallbackTable.printToStdOut("I like to eat at least %d bananas a dayrn", nBananas);