Как определить и использовать boost::function с необязательными аргументами?

Я использую класс, которому нужен какой-то метод обратного вызова, поэтому я использую boost:: function для хранения указателей функций.

мне нужно, чтобы обратный вызов имел один необязательный аргумент, но я обнаружил, что boost:: function не позволит мне определить тип необязательных аргументов, поэтому я попробовал следующий код, и он сработал.

//the second argument is optional  
typedef boost::function< int (int, char*)> myHandler;  

class A   
{  
public:  
     //handler with 2 arguments  
     int foo(int x,char* a) {printf("%s\n",a);   return 0;}; 
     //handler with 1 argument
     int boo(int x) {return 1;};       
}

A* a = new A;  
myHandler fooHandler= boost::bind(&A::foo,a,_1,_2);  
myHandler booHandler= boost::bind(&A::boo,a,_1);    

char* anyCharPtr = "just for demo";  
//This works as expected calling a->foo(5,anyCharPtr)  
fooHandler(5,anyCharPtr);  
//Surprise, this also works as expected, calling a->boo(5) and ignores anyCharPtr 
booHandler(5,anyCharPtr);   

Я был потрясен тем, что это сработало, вопрос в том, должно ли это работать и законно ли это?
есть ли лучшее решение?


person Gaby Rubin    schedule 04.03.2011    source источник
comment
ИМО, что здесь странно, это не то, где находится ваш //surprise, а то, что вы можете объявить booHandler как тип myHandler.   -  person Benoit    schedule 04.03.2011
comment
и если бы fooHandler тоже не смог привязать литерал к char *   -  person CashCow    schedule 04.03.2011


Ответы (1)


Возможно, дыра в безопасности типа в преобразовании привязки -> функции. boost::bind возвращает не std::function, а объект функции очень сложного типа. В случае

boost::bind(&A::boo,a,_1);

как видно выше, возвращаемый объект имеет тип

boost::_bi::bind_t<
  int, 
  boost::_mfi::mf1<int,A,int>,
  boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > 
>

std::function только проверяет, является ли предоставленный объект функции "совместимым", в данном случае, может ли он быть вызван с int в качестве первого аргумента и указатель на char в качестве второго аргумента. Изучив шаблон *boost::bind_t*, мы видим, что он действительно имеет соответствующий оператор вызова функции:

template<class A1, class A2> result_type operator()(A1 & a1, A2 & a2)

Внутри этой функции второй аргумент молча отбрасывается. Это по дизайну. Из документации: Любые дополнительные аргументы молча игнорируются. (...)

person decltype    schedule 04.03.2011
comment
считать это багом или фичей? - person Gaby Rubin; 04.03.2011
comment
@GTK: документы boost.bind явно называют это функцией: boost.org/doc/libs/release/libs/bind/bind.html#with_functions - person ildjarn; 05.03.2011
comment
@ildjarn - Спасибо, я не знал об этом - соответственно обновлю пост - person decltype; 06.03.2011