2

I have a class Foo from a third party library that has a lots of setters with a string argument named as set_parameter_name(std::string value). And I need to configure an instance of the class using a simple parser that returns a needed value of the required parameter like this:

std::string value = parser.parse("parameter_name");

So the code looks like:

Foo foo = Foo();
Parser parser = Parser();
foo.set_a(parser.parse("a"));
foo.set_b(parser.parse("b"));
// lots of strings
foo.set_z(parser.parse("z");

This code is pretty ugly so I'm trying to replace it with a C++ macro. The idea is using a list of names to generate code automatically by preprocessor but I cannot imagine how to do that.

If I deal with the parameters as strings, I cannot convert it to set_param_name in macro:

#define PARAM_LIST "a", "b", "c", "d" // lots of elements

#define PARAM_SETTER(foo, param, parser) ({ \
foo.set_#param(parser.parse(param)); \ // <- as I understand, it's impossible to create a method name from a string value.
})

Foo foo = Foo();
Parser parser = Parser();
for (auto param : std::string[]{PARAM_LIST}) PARAM_SETTER(foo, param, parser);

Alternatively, I can define the list as variables, but in this case I don't know how to save a variable name when it passed to macro:

#define PARAM_LIST a, b, c, d

#define PARAM_SETTER(foo, param, parser) ({ \
foo.set_#param(parser.parse("#param"); \
})

Foo foo = Foo();
Parser parser = Parser();
std::string PARAM_LIST;
for (auto param : std::string[]{PARAM_LIST}) PARAM_SETTER(foo, param, parser); // the problem is variable name to stringify is just 'param'

The 3rd method is possibly using VA_ARGS in macro but I don't know how.

7
  • Look at en.wikipedia.org/wiki/X_macro Commented Sep 17 at 14:21
  • a##b is token glue to make ab, and #c is string-ify to make a string "c", so: foo.set_##param(parser.parse(#param); Commented Sep 17 at 14:25
  • "pretty ugly so I'm trying to replace it with a C++ macro" - a macro usually makes thins more ugly and there's usually always a better way. Avoid macros unless they are the only viable option. Commented Sep 17 at 14:42
  • @Elijay In both cases #param in macro will be replaced with "param" because macro called using variable named "param" in a loop. And therefore set_##param will be replaced to set_param. Commented Sep 17 at 14:47
  • Besides of that you are going to create a debugging hell, I'd hardly believe your PARAM_SETTER is going to work like that in a loop. This means your loop is going to generate four different functions in one single instruction. Commented Sep 17 at 14:48

1 Answer 1

10

With X MACRO,

#define LIST_OF_VARIABLES \
    X(a) \
    X(b) \
    X(c) \
    X(z) \

you might do:

#define X(var) foo.set_##var(parser.parse(#var));
LIST_OF_VARIABLES
#undef X

Demo

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

1 Comment

Thanks, I think X macro is what I actually want.

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.