1

I'm relatively new to C++ and I'm currently creating a class based on a C code I was given. In this code there are some macros that define for loops. I've heard that is better to avoid macros so I'm trying (and failing) to write them differently.

I looked at this question which suggest the use of templates and functors, even though I'm not achieving what I want.

I will give a simplify example. Let's suppose that the macro is defined as

#define for_loop (g,u,v) \
for (u = g.attribute, v = g.otherAttribute ; u <= 20 ; u = g.updateAttribute, v = g.updateOtherAttribute)

And it is used in several parts of the code for different purposes.

How would you implement it without using macros in C++?

3
  • 5
    Macros are just text-replacements. The example you've given is hard to reason about without more context. What you could do is simply not use the macro and just write out the for-loop. You don't save much and it's much clearer what you're trying to do. Commented Nov 10, 2020 at 10:14
  • 3
    The best way to avoid macros is to just not use them, and instead write C++ code. Why can't you do that here? If this needs to be generic code, consider using a template function. When combined with things like lambda expressions you can do a ton without ever having to even think about macros. Commented Nov 10, 2020 at 10:19
  • Show the definition of the type of a typical g (do you have many different types with these attributes?) and an example of the body of that loop. Commented Nov 10, 2020 at 10:24

2 Answers 2

2

First of all, if you look for "dumb" replacement for these macros, then you may be better off to just leave them alone.

If you really look for better readability of code, try to find meaningful idioms, that may not map one to one to these macros. I.e. maybe sometimes this for_loop() can be replaced with range-for loop, something like:

for (auto u : g) {
  ...
}

And sometimes may be it may be replaced with call to some standard functions like std::find() or something...

If you want to implement function that would do exactly what this macro do you can do something like this:

void for_loop(g_type g, u_type u, v_type v, std::function<void(u_type, v_type)> func) {
  for (u = g.attribute, v = g.otherAttribute ; u <= 20 ; u = g.updateAttribute, v = g.updateOtherAttribute)
  {
    func(u, v);
  }
}

And then use it like this:

  for_loop(g, u, v, [<may require capture some used vars here>](u_type u, v_type v)
  {
    ... some code ...
  });

instead of original

  for_loop(g, u, v)
  {
    ... some code ...
  }

If changes to g, u or v should be visible after loop, then references should be used instead of passing by value.

But I highly don't recommend this approach.

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

Comments

1

How would you implement it without using macros in C++?

You can write a function template:

void
for_loop (auto& g, auto& u, auto& v, const auto& body)
{
    for (u = g.attribute, v = g.otherAttribute;
         u <= 20;
         u = g.updateAttribute, v = g.updateOtherAttribute)
        body(g, u, v);
}

The details may be different depending on how the macro is used. This example follows the macro closely, but there may be a better way to express the operation. I recommend more meaningful parameter names.

4 Comments

How is auto allowed in function parameters? It doesn't compile with msvc
@AryanParekh It's a C++20 thing. You can replace them with explicit template type parameters in older versions.
Oh okay, I was really confused to see auto that's why I asked :)
@AryanParekh: If you don't need u and v outside the function, you can simplify this by making the local variables of the function instead of arguments.

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.