views:

107

answers:

4

I'm designing a method for an input handler class. Here is some pseudo code...

void InputHandler::ScanEvents( boost::function1< void, std::string& > &func ) {
   // Scan keys, determining string to pass
     // If string found, call func with string as its argument on object tied to func
}

I'm not exactly sure how to implement this, or if it is even possible, since the whole point of a function is to separate it from its caller. The idea is that an object has a private member function and a boost::function member that holds it. Whenever it calls ScanEvents on its InputHandler, it passes that function, so the ScanEvents can "activate it" whenever an appropriate event is found.

Efficiency is a concern, as this is in a domain where performance is important, and this function is called frequently.

P.S. I swear I remember reading an example like this in one of Scott Meyer's books, but I can't find it for the life of me. Maybe it was in Modern C++ Design...looking....

A: 

Usually, calling a private method on another class isn't the best idea.

You could implement an interface-style class and inherit that, and write your ScanEvents method to expect that type of input, eg:

class Notifyable {
  public:
    virtual void notify(std::string s) = 0;
};

void InputHandler::ScanEvents( Notifyable &n ) {
    // Scan keys, determining string to pass
      // If string found, call func with string as its argument on object tied to func
      n.notify(<string>);
}

I would think this might be faster too, just because you're avoiding any possible overhead with the boost::function wrapper.

sje397
You're replacing the overhead of a `boost::function` call with the overhead of a virtual function call. In practise, they're likely to be more or less the same.
Mike Seymour
Ok - but there is additional code to build in with boost, and potentially a learning curve as well.
sje397
+2  A: 

Something along the lines of

class Thingy
{
public:
    Thingy() : callback(bind(&Thingy::Callback, this, _1)) {}

    void DoStuff()
    {
        handler.ScanEvents(callback);
    }

private:
    InputHandler handler;
    function<void(string)> callback;

    void Callback(string s)
    {
        cout << "Called with " << s << endl;
    }
};

ought to do what you describe. But it would probably be more efficient for the callback to take the string by reference.

Mike Seymour
Testing this out now.
random
random
No, you didn't follow the portable syntax. Look more carefully. The templates are not named the same.
Noah Roberts
Doh! Thanks for the help!
random
+2  A: 

boost::function has a reasonably slow overhead - about 20ns per call. I wouldn't call it from an inner loop - but neither would I call any other kind of function pointer. To invoke a member function, just use boost::lambda::bind to construct an anonymous wrapper function :

ih->ScanEvents(boost::lambda::bind(&ThisClass::CallbackFunc, this, boost::lambda::_1));

One option if you need really, really high performance would be to use an inlinable template function with a boost::lambda functor parameter:

template<typename F>
double democaller(const F &f) {
    double x = 1;
    for (int i = 0; i < 1000000; i++) {
        x = f(x);
    }
    return x;
}

namespace l = boost::lambda;

void demouser() {
    std::cout << democaller(l::_1 + 1);
}

On sufficiently high optimization settings, the lambda expression can be inlined into the calling site, eliminating overhead almost entirely.

bdonlan
Though with the method you first posted you bind in the function. If you bind, say in the constructor, and save that as a member, doesn't that remove the overhead of the call? I.e. Mike Seymour's example.
random
Yes, it saves a slight amount of overhead - it's likely to be very small though, at least if you have only a small number of fixed parameters. I just wanted to keep the example simple :)
bdonlan
A: 

You might be looking for the command implementation in Modern C++ Design.

boost::function has just as much overhead as is necessary to do what it does. It's purpose is to allow you to pass around a "pointer" to any function that can respond to its interface. If you don't need this behavior then this overhead is real overhead. If you do then I honestly can't see a better approach than boost::function (it's even optimized to make sure you don't get a bunch of extra memory use from virtual functions in some implementations).

It is possible to construct a method that results in possibly inlined code but as soon as you try to store it in a generic interface you're going to get the boost::function overhead (maybe more).

What I would recommend is to just use boost::function until such time as you find you really need to replace it with something faster. THEN, and only then you write the template stuff of varying complexity to make it happen.

Simply storing the boost::function may be quite sufficient for what you're needing. You might also look at boost::signals.

Noah Roberts
Thanks for the info. Could you take a look at the comment I left in Mike's response? It's under the gcc compiler.
random