boost :: bind with null function pointer

时间:2010-01-06 02:02:14

标签: c++ boost function-pointers bind boost-bind

如果boost::bind返回对象中嵌入的函数指针是NULL / nullptr / 0,我需要采取除调用之外的操作。如何确定对象是否包含空函数指针?

附加物

  1. 我不相信我可以使用和比较boost::function,因为boost::bind返回对象与模板函数中不同的调用签名一起使用。
  2. 简化示例:
  3. 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());
    }
    

4 个答案:

答案 0 :(得分:5)

您可以绑定到虚拟函数:

void dummy() { /* has differing behaviour */ }
// ...
boost::bind(&dummy)();

...或者,假设您将Boost.BindBoost.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'对象。如果有人尝试传入常规函数指针,它将无法编译。解决这个问题需要一些模板魔法。