如果boost::bind
返回对象中嵌入的函数指针是NULL
/ nullptr
/ 0
,我需要采取除调用之外的操作。如何确定对象是否包含空函数指针?
boost::function
,因为boost::bind
返回对象与模板函数中不同的调用签名一起使用。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);
由于被调用者中的函数的arity没有改变,我可以将绑定返回对象“强制转换”为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());
}
答案 0 :(得分:5)
您可以绑定到虚拟函数:
void dummy() { /* has differing behaviour */ }
// ...
boost::bind(&dummy)();
...或者,假设您将Boost.Bind
与Boost.Function
一起使用,则返回默认构造的函数对象,并在调用之前检查empty()
:
typedef boost::function<void (void)> F;
F create() { return F(); }
void use() {
F f = create();
if(f.empty()) {
/* ... */
}
}
关于更新:
我仍然没有看到绑定到不同函数的问题如下:
template <typename BRO>
Retval do_stuff(BRO func)
{
return func();
}
if(funcPtr) {
do_stuff(boost::bind(&use_retval, boost::bind(funcPtr, a, b)));
} else {
do_stuff(boost::bind(&do_fallback, fallback));
}
如果您想将该处理移出调用代码,您可以模拟可变参数模板函数来支持变量arities:
template<class R, class T1>
boost::function<R (T1)>
bind_wrap(R (*fnPtr)(), T1& t1, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1));
else return boost::bind(&do_fallback, fallback);
}
template<class R, class T1, class T2>
boost::function<R (T1, T2)>
bind_wrap(R (*fnPtr)(T1, T2), T1& t1, T2& t2, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1, t2));
else return boost::bind(&do_fallback, fallback);
}
// ... etc. for all needed arities
do_stuff(bind_wrap(funcPtr, var1, var2, fallback));
...或者您使用上述方法生成boost::function<>
个对象或您自己的包装,并在functor.empty()
中检查do_stuff()
或类似内容。
答案 1 :(得分:1)
我会创建一个包装器对象来执行此操作。类似于以下内容
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
int aFunction(int i, int j)
{
std::cout<<"In a Function"<<std::endl;
return i+j;
}
struct DefaultingFromFnPtr : public boost::function< int(int,int) >
{
explicit DefaultingFromFnPtr( int(*fn)(int,int) ) : fn_(fn) {}
int operator()(int i, int j) const
{
if (fn_!=NULL) return fn_(i, j);
return 7;
}
int(*fn_)(int,int);
};
template<typename T>
void do_stuff( T t )
{
std::cout<<"RETURNED "<<t()<<std::endl;
}
int main( int argv, const char** argc)
{
int(*mightBeNullFnPtr)(int,int) = NULL;
if( argv>1)
{
mightBeNullFnPtr = & aFunction;
}
int var1 = 10;
int var2 = 20;
do_stuff( boost::bind( DefaultingFromFnPtr( mightBeNullFnPtr ), var1, var2 ) );
}
编译它并在没有参数的情况下运行它并将mightBeNullFnPtr设置为NULL并使用包装类调用do_stuff,然后打印输出7.使用参数运行它并将mightByNullFnPtr设置为aFunction并调用do_stuff,打印30岁。
如果你想要更多的通用性,你需要模拟DefaultingFromFnPtr包装类,但这应该很容易做到。
答案 2 :(得分:0)
我非常确定使用空指针(=绑定对象的创建)调用boost :: bind应该被视为未定义的行为,即使只在调用它时发生崩溃。 / p>
答案 3 :(得分:-1)
你将不得不破解提升。
boost :: bind返回 unspecified-n-n 。这些类唯一有效的是operator()。你知道的另一件事是它们是可复制的,并且有一个result_f的typedef(顺便说一句,这意味着你不需要结果类型的模板)。
你想要别的东西 - 所以你需要在boost中找到 unspecified -nn 的定义(可能有几个),攻击他们有一个is_null()成员函数来检查您想要的条件,然后将其称为您的测试。
当然,这是假设您确定在模板函数中总是会得到一个boost :: bind'对象。如果有人尝试传入常规函数指针,它将无法编译。解决这个问题需要一些模板魔法。