0

The following code give compile error caused by line 17:

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

void func()
{}

class A{
public:

    template <typename T>
    static void foo(T const& arg){}

    template <typename T>
    void bar(T const& arg){
        boost::bind(&A::foo<T>, arg);  //OK
        boost::function<T> functor1 = boost::bind(func); //OK
        boost::function<T> functor2 = boost::bind(&A::foo<T>, arg); //ERROR, LINE 17
    }
};

int main()
{
    A obj1;
    obj1.bar(func);
}

The question is, what the protoype of functor2 in line 17 should be?
If I really want to keep the functor2's prototype to be "boost::function<void()>, how to make the boost::bind return such a type?

The compilation error is:usr/include/boost/bind/bind.hpp:253: error: invalid initialization of reference of type 'void (&)()' from expression of type 'void (*)()'
What does it mean?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
John Crane
  • 371
  • 5
  • 14

3 Answers3

3

foo(T const& arg) takes a reference argument. In order to pass a reference argument through boost::bind, you need to wrap it with boost::ref.

boost::function<T> functor2 = boost::bind(&A::foo<T>, boost::ref(arg));
qehgt
  • 2,972
  • 1
  • 22
  • 36
brad
  • 46
  • 2
0

Have a look at What is the return type of boost::bind?

In short, I would just write

auto functor2 = boost::bind(&A::foo<T>, arg);

and compile it with gcc 4.6+ or with gcc 4.4 with --std=gnu++0x option.

Community
  • 1
  • 1
Ixanezis
  • 1,631
  • 13
  • 20
  • unfortunately, I can not turn on the cpp0x option. This sample code above is simplified and minimized from the real project code. The build harness is fixed, and can not use the new standard. – John Crane Apr 11 '12 at 20:13
0

I'm not experienced with bind, but don't you usually need an instance of the class you're calling the member function on? If you don't include it in the bind, you'll need to include it at the invocation site. Using auto for my example (I read above you can't use it, but I will for succinctness), I'll re-implement your A::bar() method:

void bar(T const& arg){
    auto barebones = boost::bind(&A::foo<T>, arg);
    // OR
    auto barebones = boost::bind(&A::foo<T>, _1, arg);
    barebones(this); // Need an instance, or a pointer to an instance of A
    boost::function<T> functor1 = boost::bind(func); // OK because func is a bare function with no arguments
    boost::function<T> functor2 = boost::bind(&A::foo<T>, this, arg); // betting that would work
    functor2(); // with my modification, I think that'll work.
}

You MAY need the _1 syntax to say the first argument takes that spot, or it may work without it. I'm not 100% sure (haven't compiled it), but based upon the documentation at the boost site (boost bind doc, boost mem_fn doc) this is what I think is happening.

Why the first part compiled, I dunno. It makes me suspect that the original syntax is OK, but you need to pass the class instance. If you're looking for a "bare" callable object that doesn't need additional arguments, you need to pass an instance (or pointer to one, or smart pointer to one) when binding.

If you're having problems deducing types, try the BOOST_AUTO() macro if you can. Doc link.

Kevin Anderson
  • 6,850
  • 4
  • 32
  • 54