Question

I've read posts/articles about lambdas, function pointers, anonymous functions in general and other related things but nothing I've seen (I think) has hit on exactly what I'm looking to do.

It seems like accomplishing this should be pretty simple, but say I have a function containing things I always want to do when called, but each time I call it I want it to run a function I describe (and only need to use once) in the argument (this anonymous function being the only argument).

Assuming this function which accepts my anonymous function as its argument is in main.cpp so it's called from main is it possible to implement this in a simple way?

Basically I'm trying to figure out the syntax in C++ for going from this:

// Some function with partially duplicated code
void OriginalA()
{
    DoThingsA();

    // unique code

    DoThingsB();
}

// Another function with partially duplicated code
void OriginalB()
{
    DoThingsA();

    // unique code

    DoThingsB();
}

To this:

// Encapsulate shared functionality
// <param name="action">User defined action</param>
void UniqueWrapper(Action action)
{
    DoThingsA();

    action();

    DoThingsB();
}

// New implmentation of A
void NewA()
{
    UniqueWrapper(() =>
    {
        // unique code
    });
}

// New implementation of B
void NewB()
{
    UniqueWrapper(() =>
    {
        // unique code
    });
}

Which I found as #1 here: http://www.wildbunny.co.uk/blog/2012/11/01/10-steps-to-becoming-a-better-programmer/

But a setup like this where literally all you would have to do for the call is:

theFunctionName(() => { /*unique things to do*/ });

If this ^^ is legal calling syntax then I'm just not sure how the parameter looks in the definition of theFunctionName, clearly it isn't (Action action) like in the example above.

Was it helpful?

Solution 2

There are multiple ways to do this, but not all will work on all platforms (e.g. because they'd require C++11 features (lambdas).

The more classic approach would be something like this (without an anonymous function):

#include <iostream>

typedef void(*Action)();

void UniqueWrapper(Action action) {
    std::cout << "Generic Code 1" << std::endl;
    action();
    std::cout << "Generic Code 2" << std::endl;
}

void CustomAction(void) {
    std::cout << "Custom Code" << std::endl;
}

int main(int argc, char **argv) {
    UniqueWrapper(&CustomAction);
    return 0;
}

Of course you could use some macro shenanigans to make this more "dynamic".

Once you accept C++11 code as well (which is required to have lambdas as explained), you can do something like this:

#include <iostream>

typedef void(*Action)();

void UniqueWrapper(Action action) {
    std::cout << "Generic Code 1" << std::endl;
    action();
    std::cout << "Generic Code 2" << std::endl;
}

int main(int argc, char **argv) {
    UniqueWrapper([](){
            std::cout << "Custom Code" << std::endl;
        });
    return 0;
}

Of course, there's room for more changes, for example you could use std::function rather than a function pointer.

OTHER TIPS

Replace the Action argument with:

template<typename Function>
void UniqueWrapper(Function action) {
  DoThingsA();
  action();  // call the passed in function
  DoThingsB();
};

Call it like this:

void NewA() {
  UniqueWrapper([]() {});
  //            ^^^^^^^
  //       C++11 lambda syntax
}

Instead of a lambda you can also use function pointers, member functions (using std::mem_fn), or functors. Every kind of callable object will work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top