Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a 'for' loop macro in C++

Perhaps it is not good programming practice, but is it possible to define a for loop macro?

For example,

#define loop(n) for(int ii = 0; ii < n; ++ ii)

works perfectly well, but does not give you the ability to change the variable name ii.

It can be used:

loop(5)
{
    cout << "hi" << " " << "the value of ii is:" << " " << ii << endl;
}

But there is no choice of the name/symbol ii.

Is it possible to do something like this?

loop(symbol_name, n)

where the programmer inserts a symbol name into "symbol_name".

Example usage:

loop(x, 10)
{
    cout << x << endl;
}
like image 987
FreelanceConsultant Avatar asked Jun 24 '14 16:06

FreelanceConsultant


People also ask

How do you define a for loop macro?

For two-way for loop which replaces both, for(auto i = 0; i < n; ++i) and for(auto i = n - 1; i >= 0; --i) in one macro. Note that the xor operator (i < n)^(st > n) complements the function appropriately. Since time overhead is minimal, it should work equally effectively.

How do you define a macro in C?

A macro is a fragment of code that is given a name. You can define a macro in C using the #define preprocessor directive. Here's an example. Here, when we use c in our program, it is replaced with 299792458 .


3 Answers

#define loop(x,n) for(int x = 0; x < n; ++x)
like image 58
prajmus Avatar answered Nov 08 '22 23:11

prajmus


In today's C++ we wouldn't use a macro for this, but we'd use templates and functors (which includes lambda's):

template<typename FUNCTION>
inline void loop(int n, FUNCTION f) {
  for (int i = 0; i < n; ++i) {
    f(i);
  }
}
// ...
loop(5, [](int jj) { std::cout << "This is iteration #" << jj << std::endl; } );

The loop function uses the variable i internally, but the lambda doesn't see that. It's internal to loop. Instead, the lambda defines an argument jj and uses that name.

Instead of the lambda, you could also pass any function as long as it accepts a single integer argument. You could even pass std::to_string<int> - not that loop would do something useful with the resulting strings, but the syntax allows it.

[edit] Via Mathemagician; you can support non-copyable functors using

template<typename FUNCTION>
inline void loop(int n, FUNCTION&& f) {
  for (int i = 0; i < n; ++i) {
    std::forward<FUNCTION>(f)(i);
  }
}

[edit] The 2020 variant, which should give better error messages when passing inappropriate functions.

inline void loop(int n, std::invocable<int> auto&& f) {
  for (int i = 0; i < n; ++i) {
    std::invoke(f,i);
  }
}
like image 33
MSalters Avatar answered Nov 08 '22 21:11

MSalters


#define loop(x, n) for(int x = 0; x < n; ++ x)

Something like this?

#include <iostream>
using namespace std;

#define loop(x, n) for(int x = 0; x < n; ++ x)

int main() {

    loop(i, 10)
    {
        cout << i << endl;
    }

    return 0;
}
like image 39
ArthurChamz Avatar answered Nov 08 '22 22:11

ArthurChamz