问题
I have a structure that I pass around my application which contains a bunch of callback functions:
typedef struct {
std::function<void (void)> f1;
std::function<void (int)> f2;
std::function<int (float *)> f3;
// ... and so on
} CallbackTable;
I handle state control within the application by binding different functions to the various callbacks, depending upon the current system state; it works fine.
What I'd now like to do is to add a couple of extra callbacks with signatures containing variable numbers of arguments, akin to printf: for example,
std::function<int (const char * format, ...)> printToStdOut;
This doesn't work. In Visual C++, I get an error message stating:
error C2027: use of undefined type 'std::_Get_function_impl<_Fty>'
I'm still feeling my way through this area of C++ syntax and would very much appreciate any advice on how I should proceed from here. My overriding objective is to be able to make a call along the lines of:
myCallbackTable.printToStdOut("I've just eaten %d bananas\r\n", nBananas);
...and to have the output directed to a console, to a file or to a GUI window, according to the system state.
回答1:
Edit: Original answer was wrong, modified but still may not be a good answer, leaving it here for educational purposes:
Many variable argument functions have a va_list version. printf
for example has vprintf
. These variants explicitly take a va_list instead of an ellipses.
#include <iostream>
#include <functional>
#include <cstdarg>
int main()
{
std::function<int(const char*,va_list)> test2(vprintf);
return 0;
}
Invoking it, however, is a pain.
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);
}
What was wrong with original post (thanks /u/T.C.): std::function<int(const char*,va_list)> test2(printf)
compiles, which I took to meaning it "worked". However it compiles because printf can accept arguments of any type (including a va_list), and std::function
only checks if it can be invoked in that way.
回答2:
Following on from what @MadScienceDreams suggested, this has worked rather well for me...
Firstly, I defined variable-argument versions of the std::function objects in the struct, then used the fact that this is C++ not C to add some methods as well:
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;
The default implementations of the variable-argument functions, for console output, were then (after having declared 'using namespace std::placeholders;' without which the syntax is unmanageable):
myCallbackTable.vprintToStdOut = std::bind(vfprintf, stdout, _1, _2);
myCallbackTable.vprintToStdErr = std::bind(vfprintf, stderr, _1, _2);
...and from this point, I can use exactly the syntax I was hoping to use:
myCallbackTable.printToStdOut("I like to eat at least %d bananas a day\r\n", nBananas);
来源:https://stackoverflow.com/questions/25671626/can-stdfunction-be-used-to-store-a-function-with-variadic-arguments