Question

I'm trying to pass member function wrapped to stand-alone function via boost::bind. The following is the reduced sample.

// Foo.h
typedef const std::pair<double, double> (*DoubleGetter)(const std::string &);

class Foo : private boost::noncopyable {
public:
  explicit Foo(const std::string &s, DoubleGetter dg);
};

// Bar.h
struct Bar {
  const std::pair<double, double> getDoubles(const std::string &s);
};

// main.cpp
boost::shared_ptr<Bar> bar(new Bar());

std::string s = "test";
Foo foo(s, boost::bind(&Bar::getDoubles, *(bar.get()), _1));

However I got compiler error with the text:

/home/Loom/src/main.cpp:130: error: no matching function for call to 
‘Foo::Foo
( std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, boost::_bi::bind_t
  < const std::pair<double, double>
  , boost::_mfi::mf1
    < const std::pair<double, double>
    , Bar
    , const std::string&
    >
  , boost::_bi::list2
    < boost::_bi::value<Bar>
    , boost::arg<1>
    >
  >
)’

/home/Loom/src/Foo.h:32: note: candidates are: 
Foo::Foo(const std::string&, const std::pair<double, double> (*)(const std::string&))

/home/Loom/src/Foo.h:26: note:
Foo::Foo(const Foo&)

What the problem with the code and how to avoid such a problems?

Was it helpful?

Solution

Member function pointers do not include a context (as opposed to a lambda or boost::function). To make the code work you need to replace your type definition of DoubleGetter to:

typedef boost::function<const std::pair<double, double>(const std::string&)> DoubleGetter;

Also there is also no need to dereference the smart pointer when you supply the context (Bar)(if you intend to do so anyway you can use the shorthand dereference operator directly):

// Pass the pointer directly to increment the reference count (thanks Aleksander)
Foo foo(s, boost::bind(&Bar::getDoubles, bar, _1));

I also noticed that you define a normal function pointer. In case you want to avoid use of boost::function completely you can use the following approach (I excluded non-altered parts):

typedef const std::pair<double, double> (Bar::*DoubleGetter)(const std::string &);

class Foo : private boost::noncopyable {
public:
  explicit Foo(const std::string &s, Bar& bar, DoubleGetter dg);
  // Call dg by using: (bar.*dg)(s);
};

// Instantiate Foo with:
Foo foo(s, *bar, &Bar::getDoubles);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top