我有一个结构,我传递给我的应用程序,其中包含一堆回调函数:
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 bananas\r\n", nBananas);
...并根据系统状态将输出定向到控制台,文件或GUI窗口。
答案 0 :(得分:5)
编辑:原始回答是错误的,修改后但仍然可能不是一个好的答案,留待它用于教育目的:
许多变量参数函数都有va_list版本。例如printf
有vprintf
。这些变体显式采用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
只检查它是否可以以这种方式调用。
答案 1 :(得分:0)
根据@MadScienceDreams的建议,这对我来说相当不错......
首先,我在struct中定义了std :: function对象的变量参数版本,然后使用了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;
对于控制台输出,变量参数函数的默认实现是(在声明'using namespace std :: placeholders;'之后,语法无法管理):
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 day\r\n", nBananas);