0

I'm using boost::function like this:

template<class T1>
void run(boost::function<void (T1)> func, string arg)
{
    T1 p1 = parse<T1>(arg);
    func(p1);
}

When used like this, everything is ok:

void test1(int i)
{
    cout << "test1 i=" << i << endl;
}

...

boost::function<void (int)> f = &test1;
run(f, "42");

I want to be able to pass the raw function pointer directly, so I overload the run() function like this:

template<class T1>
void run(void (*func)(T1), string arg)
{
    T1 p1 = parse<T1>(arg);
    (*func)(p1);
}

...

run(&test1, "42"); // this is OK now

Now, I want to be able to pass the result of boost::bind to the run() function. Like this:

void test2(int i, string s)
{
    cout << "test2 i=" << i << " s=" << s << endl;
}

...

run(boost::bind(&test2, _1, "test"), "42"); // Edit: Added missing parameter 42

But this wont compile: Edited

bind.cpp: In function ‘int main()’:
bind.cpp:33:59: error: no matching function for call to ‘run(boost::_bi::bind_t<void, void (*)(int, std::basic_string<char>), boost::_bi::list2<boost::arg<1>, boost::_bi::value<std::basic_string<char> > > >, std::string)’
bind.cpp:33:59: note: candidates are:
bind.cpp:7:6: note: template<class T1> void run(boost::function<void(T1)>, std::string)
bind.cpp:14:6: note: template<class T1> void run(void (*)(T1), std::string)

How should I overload run() to accept boost::bind()?

Edit 2

I know I can do it like this:

boost::function<void (int)> f = boost::bind(&test2, _1, string("test"));
run(f, "42");

But I'd like the usage to be less verbose.

Edit 3

Changed run() prototype from run(boost::function<void (T1)>, T1) to run(boost::function<void (T1)>, string) to elaborate the actual use case. Ref. Igor R.'s answer

The entire source file may be obtained here

anorm
  • 2,255
  • 1
  • 19
  • 38
  • There is no such thing as an "implicit cast". A cast is something you write in your source code to tell the compiler to do a conversion. There are conversions that the compiler can do without a cast; such a conversion is an "implicit conversion". When you use a cast it is an "explicit conversion". – Pete Becker Apr 09 '13 at 10:03
  • Indeed. The question title should be changed. – anorm Apr 09 '13 at 11:05

1 Answers1

1

Neither function nor the result type of bind are convertible to a function pointer, so you can't pass them to run function with its current signature.

However, you can change run signature to allow it accepting any callable:

template<class F, class A1>
void run(F f, A1 arg)
{
  f(arg);
}

Now you can pass a pointer function, a binder, boost::function or what ever callable you wish - as long as it expects 1 argument. (Note however, that with this trivial signature run wouldn't forward the arguments to f seamlessly.)

Igor R.
  • 14,716
  • 2
  • 49
  • 83
  • Yes, the solves the problem I have described (+1). However, the actual run() function needs to know the type of the argument and the argument is not part of the real world function. – anorm Apr 09 '13 at 07:55
  • The real world function uses the argument type to call a templated string parser so that I can call a function, giving it string arguments, and the run() function parses the arguments as correct types and invokes the function – anorm Apr 09 '13 at 07:56
  • @Dr. Sbaitso I.e., `run` should accept a callable that expects 1 argument of of type `T`, and this type should be automatically deduced from the signature of the actual callable passed to `run`? Well, at the moment I can't figure out how to do this. Without auto-deduction it would be quite trivial: ` template < class A1, class F > void run(F f, string a) { T1 p1 = parse < T1 > (a); f(p1); } ` Call like this: `run < int > (test2, yourString);` – Igor R. Apr 09 '13 at 09:00