例如,这无法编译:
std::function<decltype(printf)> my_printf(printf);
使用gcc,错误消息显示为:
error: variable 'std::function<int(const char*, ...)> my_printf' has initializer but incomplete type
std::function<decltype(printf)> my_printf(printf);
起初我认为这是gcc中的一个错误,但后来我看了标准,看起来这样就不支持了。这是什么技术原因?
答案 0 :(得分:7)
问题是实施问题。让我们说这是可能的。然后std::function
必须声明(在printf的情况下)
int operator()(char* fmt, ...)
当被调用时,它必须将...的内容传递给您指定的任何对象。问题在于它不知道如何知道如何将其传递下来,这是一个问题。 printf()解析格式,但其他人使用其他机制('end'值很受欢迎)。
对于printf系列函数,我建议您查看vXXX版本(例如vprintf)。由于它们使用定义良好的参数(最后一个是变量参数列表),因此可以将std::function
绑定到这些版本。
编辑:
然而,你可以做的是编写自己的使用vprintf
函数的包装器,并处理vararg-&gt; va_list转换。
#include <cstdio>
#include <cstdarg>
#include <functional>
class PrintWrapper
{
public:
PrintWrapper() = default;
template<typename T>
PrintWrapper( T&& t) : func(std::forward<T>(t))
{
}
int operator()(char const* format, ...)
{
va_list args;
va_start(args, format);
int result = func(format, args);
va_end(args);
return result;
}
private:
std::function< int(char const*, va_list)> func;
};
int main()
{
// Note, you have to use the 'v' versions
PrintWrapper p = std::vprintf;
p("%d %d %s\n", 1,2, "hello");
char buffer[256];
using namespace std::placeholders;
p = std::bind(std::vsnprintf, buffer, sizeof(buffer), _1, _2 );
p("%lf %s\n", 0.1234, "goodbye");
// Since the previous step was a wrapper around snprintf, we need to print
// the buffer it wrote into
printf("%s\n", buffer);
return 0;
}
答案 1 :(得分:0)
编写自己的模板类。
template<typename F>
struct function2
{
F f;
template<typename... Args>
decltype(auto) operator()(Args&&... a)
{
return f(a...);
}
};
function2 a{ printf };
a("%d %u %x %p %s", 1, 1, 1, &a, "test");