Zythos
Zythos

Reputation: 180

Repeated function calls with a single argument changing in C++

I have a repeated pattern in my code

enum { OUTSIDE_BSPH = 0, INSIDE_BSPH = 1 };
bool bsph = true;
//...
bsph = false;

f(OUTSIDE_BSPH, arg1, arg2, arg3, arg4, arg5);
if (bsph) {
  f(INSIDE_BSPH, arg1, arg2, arg3, arg4, arg5);
}

g(OUTSIDE_BSPH, arg6, arg7, arg8);
if (bsph) {
  g(INSIDE_BSPH, arg6, arg7, arg8);
}

h(OUTSIDE_BSPH, arg3, arg4, arg5);
if (bsph) {
  h(INSIDE_BSPH, arg3, arg4, arg5);
}
// ...

that I would like to simplify. Could it be transformed into something like

caller(bsph, f, arg1, arg2, arg3, arg4, arg5);

caller(bsph, g, arg6, arg7, arg8);

caller(bsph, h, arg3, arg4, arg5);

// ...

without using pointers?

Upvotes: 0

Views: 60

Answers (1)

Deduplicator
Deduplicator

Reputation: 45664

There are many ways. You can use the preprocessor:

#define CALL(f, ...) do { \
        f(OUTSIDE_BSPH, __VA_ARGS__); \
        if (bsph) \
            f(INSIDE_BSPH, __VA_ARGS__); \
    } while(0)

CALL(f, arg1, arg2, arg3, arg4, arg5);
CALL(g, arg6, arg7, arg8);
CALL(h, arg3, arg4, arg5);

#undef CALL

Just keep the area where your macro is defined small, and there shouldn't be any problems.

Or you can use templates and lambdas:

template <class F>
void call(bool bsph, F f) {
    f(OUTSIDE_BSPH);
    if (bsph)
        f(INSIDE_BSPH);
}

call(bsph, [&](int x){ f(x, arg1, arg2, arg3, arg4, arg5); });
call(bsph, [&](int x){ g(x, arg6, arg7, arg8); });
call(bsph, [&](int x){ h(x, arg3, arg4, arg5); });

If you allowed for at least C++14, I would have preferred using a generic lambda, which isn't too far from the simplicity of the first solution:

auto call = [&](auto f){
    f(OUTSIDE_BSPH);
    if (bsph)
        f(INSIDE_BSPH);
};

call([&](int x){ f(x, arg1, arg2, arg3, arg4, arg5); });
call([&](int x){ g(x, arg6, arg7, arg8); });
call([&](int x){ h(x, arg3, arg4, arg5); });

Upvotes: 1

Related Questions