使用 boost::bind 的访问者模式重载函数
我正在尝试将访问者模式添加到我的代码中,并希望尽可能保持通用。更具体地说,我希望不必将回调函数硬编码到我的 accept
函数中。因此,作为 accept
函数的参数,我给出一个 boost::function
对象,然后由访问的对象调用该对象。
然而,我的问题是,我无法绑定到重载函数(因为 boost::bind 不知道要绑定到哪个确切函数),并且我无法将重载函数转换为正确的函数,因为我不知道不知道所访问类的确切类型(这很重要)。
有什么办法可以创造出我想要的东西吗?我进行了搜索,但只发现了有关如何解决绑定问题的问题(这是通过强制转换,这是我无法做到的)。
下面是一些无法编译的代码,但显示了我想要归档的内容:
#include <string>
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct A
{
virtual void acceptVisitor (boost::function<void (A const &)> callbackFnc)
{
callbackFnc(*this);
}
};
struct B : virtual public A {};
std::string printMe (A const & a) { return "A"; }
std::string printMe(B const & a) { return "B"; }
int main()
{
std::vector<std::string> stringVector;
boost::function<void (A const &)> bindedFnc = boost::bind(&std::vector<std::string>::push_back,
&stringVector, boost::bind(&printMe, _1));
A A1;
B A2;
A1.acceptVisitor(bindedFnc);
A2.acceptVisitor(bindedFnc);
}
[编辑]修复了示例代码,因为以前的版本(如ildjarn所说)没有'实际上并没有调用 accept
函数。
I'm trying to add a Visitor pattern to my code and want to keep this as general as possible. More specificly, I'd like not having to hardcode the callback function into my accept
function. So, as a parameter to the accept
function, I give a boost::function
object, which is then called by the visited object.
My problem is, however, that I can't bind to overloaded functions (because boost::bind doesn't know which exact function to bind to) and I can't cast the overloaded function to the correct one, because I don't know the exact type of the visited class (this is important).
Is there any way to create what I want? I searched SO, but found only questions about how to fix the bind issue (which is by casting, which is something I can't do).
Below is some code that does not compile, but shows what I'd like to archieve:
#include <string>
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct A
{
virtual void acceptVisitor (boost::function<void (A const &)> callbackFnc)
{
callbackFnc(*this);
}
};
struct B : virtual public A {};
std::string printMe (A const & a) { return "A"; }
std::string printMe(B const & a) { return "B"; }
int main()
{
std::vector<std::string> stringVector;
boost::function<void (A const &)> bindedFnc = boost::bind(&std::vector<std::string>::push_back,
&stringVector, boost::bind(&printMe, _1));
A A1;
B A2;
A1.acceptVisitor(bindedFnc);
A2.acceptVisitor(bindedFnc);
}
[Edit] Fixed example code, because previous version (as ildjarn remarked) didn't actually call the accept
function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这应该能让你成功一半。它使用 Boost 1.46.0 使用 Visual C++ 2010 和 g++ 4.5.1 进行编译。它不能使用 Visual C++ 2010 C++0x
实现进行编译;我还不确定为什么。设置:
演示:
结果:
这就是为什么这只是解决方案的一半:您不能将调用
boost::bind
的结果存储在boost::function 中
。问题是,当您使用boost::function
来存储绑定函数对象时,它将始终传递const A&
作为绑定函数的参数。即使您使用
D
参数调用boost::function
对象,它也会转换为const B&
。当您使用boost::function
时,很多类型信息都会丢失;这种类型信息的丢失是使 boost::function 可以用作通用可调用对象容器所必需的。但这并不意味着您不能传递绑定的函数对象;您只需使用模板来防止类型信息丢失:
不幸的是,为了不丢失类型信息,您必须将绑定的函数对象传递给函数模板。这意味着您将
acceptVisitor
设为虚拟成员函数的想法不适用于此解决方案(不可能有虚拟函数模板)。无论如何,希望这对您有帮助。
This should get you halfway there. It compiles with Visual C++ 2010 and g++ 4.5.1 using Boost 1.46.0. It does not compile with the Visual C++ 2010 C++0x
<functional>
implementation; I'm not yet sure why.The setup:
The demonstration:
The result:
Here's why this is only half of the solution: you can't store the result of the call to
boost::bind
in aboost::function
. The problem is that when you use aboost::function<void(const B&)>
to store the bound function object, it will always pass aconst A&
as an argument to the bound function.Even if you call the
boost::function
object with aD
argument, it gets converted to aconst B&
. A lot of type information is lost when you use aboost::function
; this loss of type information is necessary to makeboost::function
usable as a generic callable object container.That doesn't mean that you can't pass the bound function object around, though; you just have to use templates to prevent type information from getting lost:
It is unfortunate that in order not to lose type information you have to pass the bound function object to a function template. It means that your idea of making
acceptVisitor
a virtual member function won't work with this solution (it isn't possible to have a virtual function template).In any case, hopefully this is helpful to you.
也许您会发现 Loki 库中的通用访客模板很有用,
请参阅 http://loki-lib.sourceforge.net
Perhaps you will find the generic Visitor template from the Loki library useful
See http://loki-lib.sourceforge.net