Почему этот код, использующий `:: boost :: bind`, получает ошибку компилятора? - PullRequest
2 голосов
/ 02 февраля 2010

Этот код:

#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <iostream>

class Recorder : public ::boost::signals::trackable {
 public:
   void signalled() {
      const void *me = this;
      ::std::cerr << "Recorder at " << me << " signalled!\n";
   }
};

void signalled()
{
   ::std::cerr << "Signalled!\n";
}

int main(int argc, const char *argv[])
{
   ::boost::signal<void ()> sig;
   sig.connect(&signalled);
   {
      Recorder r;
      sig.connect(::boost::bind(&Recorder::signalled, &r, _1));
      sig();
   }
   sig();
   return 0;
}

генерирует эти ошибки компилятора:

In file included from move_constructor.cpp:2:
/usr/include/boost/bind.hpp: In instantiation of ‘boost::_bi::result_traits<boost::_bi::unspecified, void (Recorder::*)()>’:
/usr/include/boost/bind/bind_template.hpp:15:   instantiated from ‘boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >’
move_constructor.cpp:25:   instantiated from here
/usr/include/boost/bind.hpp:67: error: ‘void (Recorder::*)()’ is not a class, struct, or union type
In file included from /usr/include/boost/function/detail/maybe_include.hpp:13,
                 from /usr/include/boost/function/function0.hpp:11,
                 from /usr/include/boost/signals/signal_template.hpp:38,
                 from /usr/include/boost/signals/signal0.hpp:24,
                 from /usr/include/boost/signal.hpp:19,
                 from /usr/include/boost/signals.hpp:9,
                 from move_constructor.cpp:1:
/usr/include/boost/function/function_template.hpp: In static member function ‘static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’:
/usr/include/boost/function/function_template.hpp:904:   instantiated from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:720:   instantiated from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:1040:   instantiated from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/signals/slot.hpp:111:   instantiated from ‘boost::slot<SlotFunction>::slot(const F&) [with F = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, SlotFunction = boost::function<void()>]’
move_constructor.cpp:25:   instantiated from here
/usr/include/boost/function/function_template.hpp:152: error: no match for call to ‘(boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >) ()’

Это с g ++ 4.4.1 на коробке Fedora 11 с установленным пакетом Fedora 11 boost-1.37.0.

Этот код кажется мне совершенно кошерным. Я не понимаю, что здесь происходит, и лабиринт ошибок, связанных с расширением шаблона, очень запутан. Кто-нибудь знает в чем проблема?

1 Ответ

6 голосов
/ 02 февраля 2010
sig.connect(::boost::bind(&Recorder::signalled, &r, _1));

Какой здесь будет заполнитель _1? Это не нужно, подключение ожидает функцию void -> void. Если вы удалите ненужный заполнитель, код скомпилируется.

Вы предоставляете &Recorder::signalled - функцию-член типа void Recorder::(void), правильно связываете указатель Recorder, меняя его на void -> void, а затем дополнительно оставляя заполнитель _1 - что очевидно неправильно.

...