повышение:: свяжите с пустыми указателями функции

Если указатель функции встраивается в a boost::bind эхо-сигнал NULL/nullptr/0, Я должен принять меры кроме вызова его. Как я могу определить, содержит ли объект пустой указатель функции?

Приложения

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

Решение

Так как арность функции в вызываемом не изменяется, я могу "бросить" связывать эхо-сигнал в a 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());
}
7
задан Matt Joiner 15 January 2010 в 00:49
поделиться

4 ответа

можно либо привязать к фиктивной функции:

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

.
5
ответ дан 7 December 2019 в 12:21
поделиться

Я уверен, что вызов boost::bind с нулевым указателем (= создание объекта bind) следует считать неопределенным поведением, даже если падение произойдет только при его вызове.

.
0
ответ дан 7 December 2019 в 12:21
поделиться

Я бы создал оберточный объект, чтобы сделать это. Что-то вроде следующего

#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 ) );
}

Скомпилируйте это и запустите его без аргументов и он установит mayBeNullFnPtr в NULL и вызовет do_stuff с классом-оберткой, и так распечатает 7. Запустите его с аргументом и он установит mayByNullFnPtr в aFunction и вызовет do_stuff с этим, распечатает 30.

Если вам нужно больше генерации, то вам понадобится шаблон класса-обертки DefaultingFromFnPtr, но это должно быть довольно легко сделать.

1
ответ дан 7 December 2019 в 12:21
поделиться

Вам придется взломать повышение.

Boost :: Bind возвращается Unspecified-N-N . Единственное, что справедливо связано с этими классами, является оператором (). Единственная вещь, которую вы знаете, состоит в том, что они копируют конструируемые и имеют Typedef для RESalvy_Type (который, кстати, означает, что вам не нужен шаблон для типа результата).

Вы хотите что-то еще - поэтому вам нужно найти определение Unspecified-Nn в Boost (там, возможно, несколько), взломать их, чтобы иметь функцию IS_NULL (), которая проверяет условия Вы хотите, а затем назовите это как ваш тест.

Это, конечно, при условии, что вы уверены, что вы всегда получите усиление :: Bind'Ed Object в вашей функции шаблона. Если кто-то пытается пройти регулярное указатель функции, он не скомпировался. Работая вокруг этого потребуется некоторая магия шаблона.

-1
ответ дан 7 December 2019 в 12:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: