为什么不能std :: function绑定到C风格的可变函数? [英] Why can't std::function bind to C-style variadic functions?

查看:349
本文介绍了为什么不能std :: function绑定到C风格的可变函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,这无法编译:



std :: function< decltype(printf)> my_printf(printf);



使用gcc时,错误消息如下:

 错误:variable'std :: function< int(const char *,...)> my_printf'具有初始化器但不完整的类型
std :: function< decltype(printf)> my_printf(printf);

一开始我以为这是gcc中的一个错误,然后我看看标准像这样只是不支持。这是什么技术原因?

解决方案

问题是一个实现。让我们说这是可能的。 std :: function 必须声明(在printf的情况下)



int operator()(char * fmt,...)



当调用时,它必须传递...的内容。到你分配的任何对象。问题是,它不知道足够的关于知道如何传递这个问题的论点,这是一个问题。 printf()解析格式,但其他人使用其他机制(一个'end'值是受欢迎的)。



对于printf系列函数,我建议你看看vXXX版本(例如vprintf)。由于它们使用定义良好的参数(最后一个是可变参数列表),因此可以将 std :: function 绑定到这些版本。



编辑:



但你可以做的是编写自己的包装器,使用 vprintf 函数,并处理vararg-> 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()
{
//注意,你必须使用'v'版本
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\\\
,0.1234,goodbye);

//因为上一步是snprintf的包装,我们需要打印
//它写入的缓冲区
printf(%s\\\
,buffer );

return 0;
}

http://ideone.com/Sc95ch


For example, this fails to compile:

std::function<decltype(printf)> my_printf(printf);

With gcc, the error message reads:

error: variable 'std::function<int(const char*, ...)> my_printf' has initializer but incomplete type
     std::function<decltype(printf)> my_printf(printf);

At first I thought this was a bug in gcc, but then I looked at the standard and it looks like this just isn't supported. What's the technical reason for this?

解决方案

The issue is one of implementation. Let's say it was possible. Then std::function would have to declare (in the case of printf)

int operator()(char* fmt, ...)

When called, it would then have to pass the contents of ... to whatever object you assigned. The issue is that it doesn't know enough about the arguments to know HOW to pass that down, which is an issue. printf() parses the format, but others use other mechanisms (an 'end' value is popular).

For the printf family of functions, I suggest you look at the vXXX versions (e.g. vprintf). Since they use well defined arguments (the last one being the variable argument list), it would be possible to bind std::function to those versions.

Edit:

What you can do, however, is write your own wrapper that uses the vprintf functions, and handles the vararg-> va_list conversion.

#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;
}

http://ideone.com/Sc95ch

这篇关于为什么不能std :: function绑定到C风格的可变函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆