7

如果嵌入在boost::bind返回对象中的函数指针是NULL// nullptr0我需要采取行动而不是调用它。如何确定对象是否包含空函数指针?

附加物

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

解决方案

由于被调用者中函数的数量不变,我可以将绑定返回对象“强制转换”为 aboost::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

4 回答 4

6

您可以绑定到虚拟函数:

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

...或者,假设您Boost.Bind与 with 一起使用,返回一个默认构造的函数对象并在调用它之前进行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));
}

如果您想将该处理移出调用代码,您可以模拟可变参数模板函数以支持可变参数:

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()

于 2010-01-06T02:10:57.767 回答
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。使用参数运行它,它会将 mayByNullFnPtr 设置为 aFunction 并使用它调用 do_stuff,打印出 30。

如果您想要更多的通用性,您将需要模板化 DefaultingFromFnPtr 包装类,但这应该很容易做到。

于 2010-01-11T03:33:23.797 回答
0

我很确定使用空指针(=创建绑定对象)调用 boost::bind 应该被视为未定义的行为,即使崩溃仅在调用它时发生。

于 2010-01-06T02:08:25.290 回答
-1

你将不得不破解提升。

boost::bind 返回unspecified-nn。对这些类唯一有效的是 operator()。您唯一知道的另一件事是它们是可复制构造的,并且具有 result_type 的 typedef(顺便说一句,这意味着您不需要结果类型的模板)。

你想要别的东西 - 所以你需要在 boost 中找到unspecified-nn的定义(可能有几个),破解它们以拥有一个 is_null() 成员函数来检查你想要的条件,然后将它称为你的测试.

当然,这是假设您确定在模板函数中总是会得到一个 boost::bind 对象。如果有人尝试传入常规函数指针,它将无法编译。解决这个问题需要一些模板魔法。

于 2010-01-11T02:28:29.120 回答