boost::bind 与空函数指针
如果嵌入在 boost::bind
返回对象中的函数指针是 NULL
/nullptr
/0
,我需要采取除调用之外的操作。如何确定对象是否包含空函数指针?
附录
- 我不相信我可以使用和比较 boost::function ,因为 boost::bind 返回对象与模板函数中的不同调用签名一起使用。
- 简化示例:
模板
Retval do_stuff(BRO func, enum Fallback 后备) { if (func == NULL) { 返回 do_fallback(后备); } 别的 { 返回 use_retval(func()); } } do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), 回退);
解决方案
由于被调用者中函数的数量没有改变,我可以将绑定返回对象“转换”为boost::function并调用.empty()
Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback)
{
if (func.empty())
return do_fallback(fallback);
else
return use_retval(func());
}
If the function pointer embedded in a boost::bind
return object is NULL
/nullptr
/0
, I need to take action other than calling it. How can I determine if the object contains a null function pointer?
Addenda
- I don't believe I can use and compare
boost::function
s as theboost::bind
return object is used with varying call signatures in a template function. - Simplified example:
template <typename BRO> Retval do_stuff(BRO func, enum Fallback fallback) { if (func == NULL) { return do_fallback(fallback); } else { return use_retval(func()); } } do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), fallback);
Solution
Since the arity of the function in the callee does not change, I can "cast" the bind return object into a boost::function
and call .empty()
Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback)
{
if (func.empty())
return do_fallback(fallback);
else
return use_retval(func());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以绑定到虚拟函数:
...或者,假设您将
Boost.Bind
与Boost.Function
一起使用,返回默认构造的函数对象并检查对于empty()< /code>
在调用之前:
关于更新:
我仍然不明白绑定到如下所示的不同函数会出现什么问题:
如果您想将该处理移出调用代码,您可以模拟可变参数模板函数以支持变量参数:
...或者您使用上述方法生成
boost::function<>
对象或您自己的包装器,并检查functor.empty()
或do_stuff( )
。You can either bind to a dummy function:
... or, assuming you're using
Boost.Bind
together withBoost.Function
, return a default constructed function object and check forempty()
before calling it:Regarding the update:
I still don't see what the problem with binding to a different function like the following would be:
If you'd want to move that handling out of the calling code, you could emulate variadic template function to support variable arities:
... or you use the approach above to generate
boost::function<>
objects or your own wrappers and check forfunctor.empty()
or similar indo_stuff()
.我会创建一个包装对象来执行此操作。类似下面的内容
编译它并在不带参数的情况下运行它,它将 mightBeNullFnPtr 设置为 NULL 并使用包装类调用 do_stuff ,因此打印出 7。使用参数运行它,它将设置 mightByNullFnPtr 为 aFunction 并使用它调用 do_stuff ,打印出 30。
如果您想要更多的通用性,您将需要模板化 DefaultingFromFnPtr 包装类,但这应该很容易做到。
I'd create a wrapper object to do this. Something like the following
Compile this and run it with no arguments and it sets mightBeNullFnPtr to NULL and calls do_stuff with a wrapper class, and so prints out 7. Run it with an argument and it will set mightByNullFnPtr to aFunction and calls do_stuff with that, printing out 30.
If you want more genericity you will need to template the DefaultingFromFnPtr wrapper class, but that should be pretty easy to do.
我非常确定使用空指针调用 boost::bind (= 绑定对象的创建)应该被视为未定义的行为,即使崩溃仅在调用它时发生。
I'm pretty sure calling boost::bind with a null pointer (= the creation of the bind object) should be considered undefined behavior, even if the crash only happens when calling it.
你将不得不破解提升。
boost::bind 返回unspecified-nn。对这些类唯一有效的操作是operator()。您唯一知道的另一件事是它们是可复制构造的,并且有一个 result_type 的 typedef (顺便说一句,这意味着您不需要结果类型的模板)。
你想要别的东西 - 所以你需要在 boost 中找到 unspecified-nn 的定义(可能有几个),修改它们以获得一个 is_null() 成员函数来检查你想要的条件,然后将其称为您的测试。
当然,这是假设您确定您将始终在模板函数中获得 boost::bind'ed 对象。如果有人尝试传入常规函数指针,它将无法编译。解决这个问题需要一些模板魔法。
You're going to have to hack boost.
boost::bind returns unspecified-n-n. The only thing valid to do with these classes is operator(). The only other thing you know is that they are copy constructable, and have a typedef for result_type (which, by the way, means you don't need a template for result type).
You want something else - so you'll need to find the definition of unspecified-n-n in boost (there maybe several), hack them to have a is_null() member function which checks for the conditions you want, then call that as your test.
This is, of course, assuming you are certain you'll always get a boost::bind'ed object in your template function. If someone tries passing in a regular function pointer, it won't compile. Working around this will require some template magic.