0

Currently, I have a struct which I've used to create a lot of parameters, then I have to run various functions on all of them.

Function1(Mom.SayHi);
Function1(Mom.BeNice);
Function1(Mom.MindManners);

Function3(Mom.SayHi);
Function3(Mom.BeNice);
Function3(Mom.MindManners);

and so on, and the issue is that I have a very long list of parameters that will probably expand. Is there a way to run a specified function on everything in the struct, like

xAllTheY(FunctionWut,AllParams){
    FunctionWut(AllParams);
}

It seems that I can't use a function as a parameter. It may be because I'm using void functions. Am I missing an asterisk(*) or something?

I'm using MS Visual C++ 2010 Express, and I don't care about portability.

  • I'm imagining this language logical control construct called a "loop". You may want to loop in to that. – WhozCraig Nov 15 '13 at 21:27
  • @WhozCraig do you know of a way to make the loop run differently each time, though? –  Nov 16 '13 at 01:13

2 Answers2

0

C++ does not have any feature to run a function on every field of the structure. You need to write a call for each field explicitly.

The reason for that is that C++ is sort of "low level language" if comparing it with recent languages. It tends to translate into instructions what is written in the source code.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
0

I believe there are several ways to solve the task.

If you know that all functions have the same signature, you can use function pointer (or member function pointer) and array of potential arguments. Then you iterate over array of potential arguments and pass them to the function pointer. For instance:

void exec(void (*fun)(const std::string&), const std::vector<std::string>& args)
{
    for (auto& v: args) { fun(v); }
}

You can achieve the same result (indeed, even better result due to function pointer optimization) by using template function (or functor), which accepts function and arguments list. This way you can adopt arbitrary functions to the same piece of code; moreover, you can adopt functions that accept more than one argument by using std::bind. For instance:

template <typename Fun, typename ArgsContainer>
void exec(Fun fun, const ArgsContainer& args)
{
    for (auto& v: args) { fun(v); }
}

Actually, this is already done by for_each algorithm:

for_each(args.begin(), args.end(), &func);

Last but not least, you can use macros. Sometimes using macro+include to iterate over something is acceptable technique. For instance:

void exec(void (*fun)(const std::string&))
{
    #define RUN(arg) fun((arg))
    #include "run_cases.h"
    #undef RUN
}

where run_cases.h looks like:

RUN("test1");
RUN(2.0f);
RUN(anything_that_is_acceptable_as_any_function_overload);

And no, you cannot pass just the name of the struct assuming compiler will substitute it with it's members. You have to explicitly type them in; actually, you don't want every struct member to be used, implicit ones are a good candidate for exclusion.

nyrl
  • 769
  • 5
  • 15