2

Can the following function pointer passing be simplified/improved with the use of boost::function and/or boost::bind?

void PassPtr(int (*pt2Func)(float, std::string, std::string))
{
   int result = (*pt2Func)(12, "a", "b"); // call using function pointer
   cout << result << endl;
}

// execute example code
void Pass_A_Function_Pointer()
{
   PassPtr(&DoIt);
}
5
  • 1
    It depends what kind of answer you're looking for! Of course, all of the above can be simplified to cout << DoIt(12, "a", "b") << endl;, but I guess that's not what you're looking for. That said, there are no obvious opportunities to take advantage of Boost features here, as you're calling a pure function pointer, not a function object, etc. Commented Mar 10, 2013 at 14:30
  • It can be improved in that you then can use any member function or lambdas (if you have C++11 compatible compiler) too, not only plain function or static member function. And of course, with boost::bind (or std::bind) you can "bind" any number of arguments before passing the function object around. Commented Mar 10, 2013 at 14:31
  • What's fixed and what can change? If the signatures of PassPtr and DoIt are fixed then no, the code is as simple as it gets. Commented Mar 10, 2013 at 14:32
  • @Charles - all thats fixed is that I wish to pass a pointer to a function, for example DoIt, and have it called. Everything else can change. Commented Mar 10, 2013 at 14:34
  • If you want to pass a pointer to a function, then you are doing that in the simplest way possible. Commented Mar 10, 2013 at 14:42

2 Answers 2

7

You can use boost::function<> to make it possible using different types of callable objects as the function's input.

What follows is an example using C++11 (see the remarks after this example). This is how you would rewrite your function:

#include <functional>
#include <string>
#include <iostream>

void PassFxn(std::function<int(float, std::string, std::string)> func)
//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
   int result = func(12, "a", "b"); // call using function object
   std::cout << result << std::endl;
}

These are a couple of functions to test it with:

int DoIt(float f, std::string s1, std::string s2)
{
    std::cout << f << ", " << s1 << ", " << s2 << std::endl;
    return 0;
}

int DoItWithFourArgs(float f, std::string s1, std::string s2, bool b)
{
    std::cout << f << ", " << s1 << ", " << s2 << ", " << b << std::endl;
    return 0;
}

struct X
{
    int MemberDoIt(float f, std::string s1, std::string s2)
    {
        std::cout << "Member: " << f << ", " << s1 << ", " << s2 << std::endl;
        return 0;
    }

    static int StaticMemberDoIt(float f, std::string s1, std::string s2)
    {
        std::cout << "Static: " << f << ", " << s1 << ", " << s2 << std::endl;
        return 0;
    }
};

And here is the test routine:

int main()
{
    PassFxn(DoIt); // Pass a function pointer...

    // But we're not limited to function pointers with std::function<>...

    auto lambda = [] (float, std::string, std::string) -> int
    {
        std::cout << "Hiho!" << std::endl;
        return 42;
    };

    PassFxn(lambda); // Pass a lambda...

    using namespace std::placeholders;
    PassFxn(std::bind(DoItWithFourArgs, _1, _2, _3, true)); // Pass bound fxn

    X x;
    PassFxn(std::bind(&X::MemberDoIt, x, _1, _2, _3)); // Use a member function!

    // Or, if you have a *static* member function...
    PassFxn(&X::StaticMemberDoIt);

    // ...and you can basically pass any callable object!
}

And here is a live example.

REMARKS:

You can easily change std::function<> into boost::function<> and std::bind<> into boost::bind<> if you are working with C++03 (in fact, Boost.Function is what inspired std::function<> and later became part of the Standard C++ Library). In this case, instead of including the <functional> header, you will have to include the boost/function.hpp and boost/bind.hpp headers (the latter only if you want to use boost::bind).

For a further example that should give you a feeling of the power that std::function<> / boost::function<> gives you through its ability of encapsulating any kind of callable object, also see this Q&A on StackOverflow.

Sign up to request clarification or add additional context in comments.

1 Comment

Thats great! could you add one further example before I mark as answered. How would the syntax look for when DoIt is a member function being passed?
4

I assume you want to improve the functionality of PassPtr, rather than all of the sample code you gave. If you are using C++11 and can use lambda expressions, I would simplify it to just:

template <typename Func>
void PassPtr(Func f) {
  std::cout << f(12, "a", "b") << std::endl;
}

This will allow any callable object to be passed as f. The reason for taking the function by a deduced template type is to allow any lambdas that are passed to be inlined. Of course, this doesn't enforce any particular signature on the passed function (or that it should even be a callable object). For example, if you pass an int, you'll get some confusing compiler errors.

The alternative, using [boost|std]::function, is to do this:

void PassPtr(std::function<int(float, std::string, std::string)> f) {
  std::cout << f(12, "a", "b") << std::endl;
}

This will allow any kind of callable object to be passed, just as the above, but will probably not cause lambdas to be inlined.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.