在 C++ 中定义一个“for”循环宏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24392000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:43:35  来源:igfitidea点击:

Define a 'for' loop macro in C++

c++loopsfor-loopc-preprocessor

提问by user3728501

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

也许这不是一个好的编程习惯,但是否可以定义一个for循环宏?

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.

工作得很好,但不能让您更改变量 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.

但是没有选择 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".

程序员在“ symbol_name”中插入符号名称的地方。

Example usage:

用法示例:

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

回答by prajmus

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

回答by MSalters

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

在今天的 C++ 中,我们不会为此使用宏,但我们会使用模板和函子(包括 lambda 的):

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 loopfunction uses the variable iinternally, but the lambda doesn't see that. It's internal to loop. Instead, the lambda defines an argument jjand uses that name.

loop函数在i内部使用该变量,但 lambda 没有看到。它是loop. 相反,lambda 定义了一个参数jj并使用该名称。

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 loopwould do something useful with the resulting strings, but the syntax allows it.

除了 lambda,您还可以传递任何函数,只要它接受单个整数参数即可。您甚至可以通过std::to_string<int>- 这loop不会对结果字符串做一些有用的事情,但语法允许它。

[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);
  }
}

回答by ArthurChamz

#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;
}

回答by Slava

You can define a variable name as a first parameter for a macro:

您可以将变量名称定义为宏的第一个参数:

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

Note, there is a rule that most experienced programmers follow - use uppercase identifiers for macros. In your case, imagine you have a function and macro:

请注意,大多数有经验的程序员都遵循一条规则——宏使用大写标识符。在您的情况下,假设您有一个函数和宏:

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

void loop();

Now try to call that function in your code and watch what ugly error messages you are getting. Some of them could be not easy to understand at all. Even worse is having that loop function in a namespace or method in a class and does not help at all.

现在尝试在您的代码中调用该函数并观察您收到哪些丑陋的错误消息。其中一些可能根本不容易理解。更糟糕的是,在类中的命名空间或方法中使用该循环函数,根本没有帮助。

So at least have it this way:

所以至少要这样:

#define LOOP(variable, n) for(int variable = 0; variable < n; ++variable )

but better not use it at all.

但最好不要使用它。

回答by Arne

Use:

用:

#include <vector>
#include <cstdio>

using std::printf;

#define FOR(TYPE, IDENT, BEGIN, END) for(TYPE IDENT = BEGIN, IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; ++IDENT)
#define FOR_STEP(TYPE, IDENT, BEGIN, END, STEP) for(TYPE IDENT = (TYPE)(BEGIN), IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; IDENT += STEP )
#define FOR_ITER(IDENT, BEGIN, END) for(auto IDENT = BEGIN, IDENT_end = END; IDENT != IDENT_end; ++IDENT)

int main() {
  FOR(int, i, 0, 10) {
    printf("FOR i: %d\n", i);
    printf("we can even access i_end: %d\n", i_end);
  }

  FOR(auto, i, 0, 10) {
    printf("FOR auto i: %d\n", i);
  }

  std::vector<int> vec = {4, 5, 7, 2, 3, 1, 4, 9, 8, 6};

  printf("FOR with iterator: {");
  FOR(auto, it, vec.begin(), vec.end()) {
    printf("%d, ", *it);
  }
  printf("}\n");

  printf("FOR with non constant end:\n");
  FOR(long, i, 0, vec.size()) {
    printf("vec[%ld] = %d\n", i, vec[i]);
  }
  printf("\n");


  // You can set a step size
  printf("FOR_STEP(double, d, 0, 20, 2.1): ");
  FOR_STEP(double, d, 0, 20, 2.1) {
    printf(" %f ", d);
  }
  printf("\n");

  // It works with iterators that don't have "<" but only "!="
  // defined, but you probably want to use a range-based 'for' anyway.
  printf("FOR_ITER(auto, it, vec.begin(), vec.end()): ");
  FOR(auto, it, vec.begin(), vec.end()) {
    printf("%d, ", *it);
  }
  printf("\n");
}

This is the best I could come up with for a C++11 target. It makes sure the ENDargument is only evaluated once and requires that beginand endhave the same type, which is almost always the case.

这是我能想到的最好的 C++11 目标。它可以确保END参数只计算一次,并要求beginend具有相同类型的,这几乎总是如此。

Since you should not test doubles on equality with an ==or !=operator, the default FORmacros uses an <operator for comparison, this limits the usage of the macro for iterators, because they now need to have the <operator defined, too. I could not come up with one solution that works with double and arbitrary iterators alike; you can choose one macro that suits your needs better.

由于您不应该使用==or!=运算符测试双精度数,默认FOR宏使用<运算符进行比较,这限制了宏在迭代器中的使用,因为它们现在也需要<定义运算符。我无法想出一种适用于双迭代器和任意迭代器的解决方案;您可以选择一种更适合您需求的宏。

But you should not introduce all of the macros to you code, because with just one macro definition that suits most needs, the code will be much more readable.

但是您不应该向您的代码引入所有宏,因为只有一个满足大多数需求的宏定义,代码将更具可读性。

回答by t.c

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

You can try this.

你可以试试这个。

回答by Ashish

try like this- #define loop(i,n) for((i) = 0; (i) < (int)(n); (i)++)

试试这样 - #define loop(i,n) for((i) = 0; (i) < (int)(n); (i)++)

回答by Mehrshad

In competition programming, it is necessary to code as fast as you can. One way to speed up coding is using macros. Competition programmers use macro below to abbreviate "for loops" :

在竞赛编程中,有必要尽可能快地编写代码。加速编码的一种方法是使用宏。竞赛程序员使用下面的宏来缩写“for循环”:

#define For(i,j,n) for(int i=(j);i<((int)n);++i)

For example the code below will print 1 to 10.

例如,下面的代码将打印 1 到 10。

#include <stdio.h>
#define For(i,j,n) for(int i=(j);i<((int)n);++i)

int main(void)
{
   For(i, 1, 11)
   {
       printf("%d\t", i);
   }
}

But macros are dangerous, picky, and just not that safe. I really recommend you not to use them in your projects. To show this issue consider the code below.

但是宏是危险的、挑剔的,而且不是那么安全。我真的建议你不要在你的项目中使用它们。要显示此问题,请考虑以下代码。

#include <stdio.h>
#define For(i,j,n) for(int i=(j);i<((int)n);++i)

int main(void)
{
   int end = 10;
   For(i, 1, end++)
   {
       printf("%d\t", i);
   }
}

If you run the code, you'll see that the program never stop working, although you may expect that the output should the same 1 to 10.

如果你运行代码,你会看到程序永远不会停止工作,尽管你可能期望输出应该是相同的 1 到 10。