6

Boost库bind函数的嵌套调用

 3 years ago
source link: https://blog.csdn.net/yanxiangtianji/article/details/8832559
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

问题提出:

我写了一个函数,它需要使用一个生成整数随机数的随机数发生器作为参数。然后写了一个函数来根据参数生成不同分布的随机数发生器,供前一个函数使用。我调用了boost库的一些基于特定概率分布的随机数生成函数,但是有很多函数的结果是double型的。

我的函数将随机数发生器定义为boost::function<int()>类型。很明显那些生成double的函数不能直接通过bind operator()的方式得到,而需要类型转换。而这个使用bind/function的嵌套调用就比较麻烦了。

(对于C++11的function和bind也同样有效。)

假设我有两个函数:

我希望的结果是得到一个函数对象:它使用gen生成原始数字,然后用trans函数把它转成整形返回;即得到一个这样的函数:

我这里还是无参数的,所以不好使用lambda表达式。

最终方案与要点:

假设使用前面的函数声明,那么这个函数对象应该这么生成:
boost::function<int()> fun=boost::bind(trans,boost::bind(gen));

其中要使用两次bind!

内层的那个看似没什么用,但是如果不使用它的话,boost不会以为我们要为trans绑定的第一个参数是一个函数,而是以为我们要绑定一个具体的值,即编译器会直接把第bind的二个参数(gen)作为trans的参数,而这个gen的类型是double(void),这时编译器会报“无法将double(void)类型转换为double类型”的错误。

解决的办法就是把要为trans绑定的函数变成会自动加“()”的东西,这就可以使用函数嵌套调用(数学意义上的而非编程意义的),把调用行为一直转移到内层。

同样地,其他参数形式的(需要使用lambda库)、多层的函数嵌套绑定,都应该注意要把内层的函数通过bind变成一个可传递的对象,而不能直接写函数名

bind绑定的各个东西都是对象(包括基本数据类型),是不支持把参数直接绑定为函数的,要这边做必须先把函数变成可以自由传递的对象!

另外不要以为你的参数已经是函数对象了就可以直接写了,还要再写bind(),具体原因还不清楚。

其他经验:

1,static_cast<T>()是运算符而不是函数!所以不能绑定。

2,boost/lambda/casts.hpp提供的ll_static_cast<T>虽然是函数,但是需要注意的是它是有两个模板参数的模板函数,在绑定的时候我们不能给出参数的实际类型(外侧的bind函数给ll_static_cast提供的是funnction<int()>的类型而不是int),因而也不能使用ll_static_cast,要自己写转换函数。

3,bind和lambda/bind有冲突,而且很多功能重叠,用一个就好了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK