为什么类型的boost ::绑定店论据,而不是通过该函数期望的类型? [英] Why does boost::bind store arguments of the type passed in rather than of the type expected by the function?

查看:92
本文介绍了为什么类型的boost ::绑定店论据,而不是通过该函数期望的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的的boost ::绑定

从的boost ::绑定文档:


  

这需要结合被复制并返回的函数对象在内部举行的参数。


我曾以为,这是正在举行的副本的类型是基于函数的签名。但是,它实际上是基于在传递的值的类型。

在我的案件的隐式转换是发生转换在绑定前pression由函数接收的类型使用的类型。我期待这种转换在结合部位发生,但是当使用所产生的函数对象它发生。

在回想起来,我应该已经能够从事实算出这个是使用boost ::绑定给了错误,当类型不兼容的仅在调用点,而不是绑定网站

我的问题是:
为什么提高::绑定工作,这种方式?


  1. 这似乎给糟糕的编译器错误消息

  2. 这似乎是效率较低时隐式转换发生,有多个调用函子

不过,考虑好如何加速设计我猜是有原因的。从的std :: bind1st / bind2nd继承了它的行为?是否有一个微妙的原因,这将是硬/不可能实现?别的东西完全?

要测试第二个理论,我写了一个小code片段,似乎工作,但也有可能是我还没有占到,因为它只是一个片段绑定的特点:

 命名空间B =提振;
模板< R级,B1级,A1级>
   B :: _双:: bind_t< R,R(*)(B1),类型名B :: _双:: list_av_1< B1> ::类型>
   mybind(R(* f)项(B1)中,A a1)中
{
   typedef的R(* F)(B1);
   的typedef typename的B​​ :: _双:: list_av_1< B1> ::类型LIST_TYPE;
   回报B :: _双:: bind_t< R,F,LIST_TYPE> (F,LIST_TYPE(B1(A1)));
}结构转换
{
   敞篷(int类型的):B(A){}
   INT B:
};INT富(敞篷巴)
{
   返回2 + bar.b;
}无效mainFunc()
{
   INT X = 3;
   B ::功能< INT()> funcObj = mybind(富,X);
   的printf(VAL数:%d \\ n,funcObj());
}


解决方案

有,你的需求的参数将在调用点处理不同的情况。

第一个例子是,调用一个成员函数,在那里你可以去拜访对象(的boost ::绑定(安培副本的成员;的std ::矢量< INT> ::的push_back,myvector)),它最有可能你不想要,否则你需要通过一个指针和粘合剂将间接引用根据需要指针(的boost ::绑定( &放大器;的std ::矢量<&INT GT; ::的push_back,&安培; myvector)) - 注两个方案可以在不同的程序意义

另一个重要用途情况下传递参数的引用的一个函数。 绑定复制的执行相当于一个传递价值的电话。该库通过辅助功能 REF CREF ,这两个指针存储到提供的包装参数的选项实际对象进行传递,以及在呼叫他们解除引用指针的位置(通过隐式转换)。如果转换为目标类型在绑定时进行,那么这将是不可能实现的。

I recently ran into a bug in my code when using boost::bind.

From the boost::bind docs:

The arguments that bind takes are copied and held internally by the returned function object.

I had assumed that the type of the copy that was being held was based on the signature of the function. However, it is actually based on the type of the value passed in.

In my case an implicit conversion was happening to convert the type used in the bind expression to the type received by the function. I was expecting this conversion to happen at the site of the bind, however it happens when the resulting function object is used.

In retrospect I should have been able to figure this out from the fact that using boost::bind gives errors when types are not compatible only at the call site, not the bind site.

My question is: Why does boost::bind work this way?

  1. It seems to give worse compiler error messages
  2. It seems to be less efficient when implicit conversion happens and there are multiple calls to the functor

But given how well Boost is designed I'm guessing there is a reason. Was it behavior inherited from std::bind1st/bind2nd? Is there a subtle reason why this would be hard/impossible to implement? Something else entirely?

To test that second theory I wrote up a little code snippet that seems to work, but there may well be features of bind I haven't accounted for since it's just a fragment:

namespace b = boost;
template<class R, class B1, class A1>
   b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
   mybind(R (*f) (B1), A1 a1)
{
   typedef R (*F) (B1);
   typedef typename b::_bi::list_av_1<B1>::type list_type;
   return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}

struct Convertible
{
   Convertible(int a) : b(a) {}
   int b;
};

int foo(Convertible bar)
{
   return 2+bar.b;
}

void mainFunc()
{
   int x = 3;
   b::function<int()> funcObj = mybind(foo, x);
   printf("val: %d\n", funcObj());
}

解决方案

There are different cases where you need the arguments to be processed at the call site.

The first such example is calling a member function, where you can either have the member called on a copy of the object (boost::bind( &std::vector<int>::push_back, myvector)) which most probably you don't want, or else you need to pass a pointer and the binder will dereference the pointer as needed (boost::bind( &std::vector<int>::push_back, &myvector )) --Note both options can make sense in different programs

Another important use case is passing an argument by reference to a function. bind will copy performing the equivalent to a pass-by-value call. The library offers the option of wrapping arguments through the helper functions ref and cref, both of which store a pointer to the actual object to be passed, and at the place of call they dereference the pointer (through an implicit conversion). If the conversion to the target type was performed at bind time, then this would be impossible to implement.

这篇关于为什么类型的boost ::绑定店论据,而不是通过该函数期望的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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