使用shared_ptr增强lambda
如果我有一个名为 Base 的多态基类以及从 Base 继承的类 Derived1 和 Derived2。然后我可以使用 boost::lambda 创建某种工厂。类似于:(
typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
这不是真正的代码,我只是想说明问题。)
这是有效的,因此我可以使用字符串在映射中进行查找,然后调用 lambda 函数来实例化该类。一切都好。
问题在于它处理的是原始指针,我更喜欢使用智能指针(std::shared_ptr)。
因此,如果我从: 更改
typedef boost::function<Base *>() Creator;
为:
typedef boost::function<std::shared_ptr<Base> >() Creator;
那么我就会从这里陷入困境。我尝试过将 boost::lambda::bind 与 boost::lambda::new_ptr 结合使用,但我运气不佳,无法克服编译错误。 (大量与模板相关的错误输出。)
我检查了 StackOverflow 中的其他类似消息,使用 boost::bind 和 boost::lambda::new_ptr 返回一个shared_ptr构造函数 是接近的,但是如果我尝试应用其解决方案,但出现上述模板错误。
如果有帮助的话,我很乐意提供示例代码和实际错误,但希望上述信息足够了。我在 GCC 4.6 上使用 boost 1.47.0,在 Fedora 15 上使用 4.7 快照。
If I have a polymorphic base class called Base as well as classes Derived1 and Derived2 which inherit from Base. I can then use boost::lambda to create a factory of sorts. Something like:
typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
(This isn't real code, I'm just trying to illustrate the problem.)
This works, so I can then do a lookup in the map using a string and then invoke the lambda function to instantiate that class. All good.
The problem with this is that it's dealing in raw pointers, I'd prefer to be using smart pointers (std::shared_ptr).
So if I change from:
typedef boost::function<Base *>() Creator;
to:
typedef boost::function<std::shared_ptr<Base> >() Creator;
Then I'm getting stuck from here. I've tried using boost::lambda::bind in conjunction with boost::lambda::new_ptr but I'm not having much luck, can't get past compilation errors. (Huge reams of template-related error output.)
I've checked other similar messages within StackOverflow, Using boost::bind and boost::lambda::new_ptr to return a shared_ptr constructor is close but if I try to apply its solution I get the template errors mentioned above.
I'm happy to provide sample code and the actual errors if it helps, but hopefully the above info is sufficient. I'm using boost 1.47.0 on GCC 4.6 as well as 4.7 snapshot on Fedora 15.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
然而,当你可以写时为什么要这么麻烦:
however, why go to the trouble when you could write:
这是一个常见问题。两种类型相关(在您的情况下是通过继承)这一事实并不意味着具有这两种类型的模板的实例化保持相同的关系。
解决方案是始终返回
shared_ptr
,因为它可以保存指向Base
或任何派生类型的指针,这将在语义上与您当前的版本兼容(即在两个版本的调用者都会获得一个指向Base
的(智能)指针顺便说一句,我会避免从工厂返回
shared_ptr
,因为你在强迫你的我更愿意返回一个原始指针(用户可以选择,但在某些情况下这是危险的)或一个unique_ptr
甚至auto_ptr< /code>,这是安全的,并且仍然允许用户选择不同的机制(即,如果您的函数返回
auto_ptr
,用户仍然可以通过执行以下操作来使用shared_ptr
shared_ptr p( f().release() );
,而相反的情况是不可能的(shared_ptr
管理的内存不能释放 用于不同的智能指针。This is a common problem. The fact that two types are related (in your case by inheritance) does not imply that the instantiations of a template with those two types maintains the same relationship.
The solution is to return always
shared_ptr<Base>
, since it can hold both pointers toBase
or any derived type, which will be semantically compatible with your current version (i.e. in both versions the caller gets a (smart)-pointer-toBase
.As an aside, I would avoid returning
shared_ptr
from a factory, as you are forcing your choice of smart pointer into all of your users. I would prefer to either return a raw pointer (the user can choose, but it is dangerous in some situations) or aunique_ptr
or evenauto_ptr
, which are safe and still allow the user to choose a different mechanism (i.e. if your function returns anauto_ptr
, the user can still use ashared_ptr
by doingshared_ptr<Base> p( f().release() );
, while the opposite is not possible (memory managed by ashared_ptr
cannot be released to use in a different smart pointer.这个快速而肮脏的返回类型适配器不仅适用于将返回类型从
Derived*
转换为Base*
,而且适用于任何可转换类型之间。为了简单起见,函数对象不带参数。使用 C++11 可变参数模板,应该可以轻松添加任意参数处理。请随意以任何您希望的方式改进这一点。This quick-and-dirty return type adapter is good not only for converting return types from
Derived*
toBase*
, but between any convertible types. For simplicity, the function-object takes no arguments. With C++11 variadic templates it should be easy to add arbitrary argument handling. Feel free to improve on this in any way you wish.但老实说,在这种复杂程度下,再使用 boost lambda 已经没有任何意义了。更简单的解决方案:
But honestly, this is the level of complexity where it doesn't really make sense to use boost lambda any more. A simpler solution: