2010-08-30 3 views
2

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

void Foo(boost::function<int()>) { ... } 
void Foo(boost::function<float()>) { ... } 
void Foo(boost::function<double()>) { ... } 

Теперь я хочу передать какой-то указатель класса метода есть:

class test 
{ 
    public: 
     float toCall() { }; 
}; 

class Wrapper 
{ 
    Wrapper() { 
    test obj; 
    Foo(boost::bind(&test::toCall, this)); 
    } 
}; 


error: no matching function for call to ‘Foo(boost::_bi::bind_t<float, boost::_mfi::mf0<float, test>, boost::_bi::list1<boost::_bi::value<Wrapper*> > >)’ 
    note: candidates are: Foo(boost::function<float()>&) 

ответ

6

Nonono это не может работать. Потому что boost::function<...> имеет шаблонный конструктор для принятия любых типов. Совместимость с сигнатурой вызова проверяется позже. Разрешение перегрузки не может решить эту проблему.

Кроме того, я думаю, вы хотите передать &obj вместо this. Попробуйте преобразовать явным образом:

Foo(boost::function<float()>(boost::bind(&test::toCall, &obj))); 

Это совершенно некрасиво, хотя, так что вы можете ввести ЬурейиЙ

void Foo(FloatHandler) { ... } 
... 
FloatHandler f(boost::bind(&test::toCall, &obj)); 
Foo(f); 

Или в конечном счете, вы могли бы сделать Foo шаблон, который принимает только любой тип вызываемой T. Я подозреваю, что это может быть самым простым, потому что в общем случае я подозреваю, что вы не знаете, к какому boost::function<...> вам нужно бросить. А как насчет людей, которые хотят вернуть std::complex<>. Так ...

template<typename T> 
void Foo(T) { ... } 
... 
Foo(boost::bind(&test::toCall, &obj)); 

Надеюсь, это поможет.

1

boost::bind не возвращает boost::function объекта. Он возвращает объект неуказанный тип, который может использоваться как функтор с соответствующим количеством параметров.

В то время как boost::function может быть преобразован из результата boost::bind, разрешение перегрузки в этом случае является «слишком сложным» для C++. (Удален мой плохой пример, который на самом деле не иллюстрирует правильную проблему).

+0

Для функции повышения, сценарий еще более злой, чем этот. Это как 'template struct A {template A (U); }; 'now, * that * выглядит неразрешимым для меня xD Обратите внимание, что вы * можете * конвертировать, если у вас есть только одна функция. Трудность состоит в том, чтобы * сравнить * две такие последовательности преобразования. В случае с функцией boost :: function это совершенно невозможно, и в вашем случае это может быть возможно, но это слишком сложно для перенаправления, чтобы беспокоиться. –

+0

@Johannes Schaub: Вы правы. Мой пример иллюстрировал совершенно другую проблему: двусмысленность вместо «неразрешимости» :) – AnT

2

В строке

Foo(boost::bind(&test::toCall, this)); 

this имеет тип Wrapper. Но привязка не может найти на нем метод toCall.

Вот исправленная версия (полная, компилирует на г ++ 4.3.2), который, вероятно, что вы пытаетесь сделать:

#include <boost/bind.hpp> 
#include <boost/function.hpp> 

void Foo(boost::function<int()>) {} 
void Foo(boost::function<float()>) {} 
void Foo(boost::function<double()>) {} 

struct test { 
    float toCall() {return 0.0f;} 
}; 

int main(int,char**) { 
    test obj; 
    boost::function<float()> tgt=boost::bind(&test::toCall,obj); 
    Foo(tgt); 
    return 0; 
} 

как ответ ноты AndreyT, в возвращаемый тип привязки является. .. бит нечетный, следовательно, явное принуждение к соответствующему типу функции.