有没有办法在for循环初始化器中定义两种不同类型的变量?

Łuk*_*Lew 6 c++ scope for-loop initializer variable-declaration

您可以在for循环中定义2个相同类型的变量:

int main() {
  for (int i = 0, j = 0; i < 10; i += 1, j = 2*i) {
    cout << j << endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是定义不同类型的变量是违法的:

int main() {
  for (int i = 0, float j = 0.0; i < 10; i += 1, j = 2*i) {
    cout << j << endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?(我不需要i在循环内使用,只是j.)

如果你完全被黑客攻击并且模糊不清,那对我来说没问题.

在这个人为的例子中,我知道你可以使用double这两个变量.我正在寻找一般答案.

请不要建议移动body之外的任何变量,可能对我不可用,因为一个迭代器必须在循环之后消失并且for语句将被包含在我的foreach宏中:

#define foreach(var, iter, instr) {                  \
    typeof(iter) var##IT = iter;                     \
    typeof(iter)::Element var = *var##IT;            \
    for (; var##_iterIT.is_still_ok(); ++var##IT, var = *var#IT) {  \
      instr;                                         \
    }                                                \
  }
Run Code Online (Sandbox Code Playgroud)

因此可以使用它:

foreach(ii, collection, {
  cout << ii;
}). 
Run Code Online (Sandbox Code Playgroud)

但我需要一些可以像这样使用的东西:

foreach(ii, collection)
  cout << ii;
Run Code Online (Sandbox Code Playgroud)

请不要引入任何运行时开销(但编译速度可能会很慢).

xia*_*ian 25

请不要建议将任何变量移到body之外,可能不适合我,因为迭代器必须在循环之后消失.

你可以这样做:

#include <iostream>

int main( int, char *[] ) {
    {
        float j = 0.0;

        for ( int i = 0; i < 10; i += 1, j = 2*i ) {
            std::cout << j << std::endl;
        }
    }

    float j = 2.0; // works

    std::cout << j << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么没用?它满足您的所有要求. (10认同)
  • @Łukasz:人工范围迫使j在范围结束时被"摧毁".它与j同时定义j相同. (3认同)
  • @Łukasz:为什么不呢?这违反了你的哪一个条件? (2认同)
  • 鉴于您想要满足的所有条件,我认为没有更实际的解决方案. (2认同)

Mik*_* G. 12

嗯,这很难看.但你可以使用对.

int main() {
  for (std::pair<int,float> p(0,0.0f); 
       p.first < 10; 
       p.first += 1, p.second = 2*p.first) {
    cout << p.second << endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 想用boost :: tuple回答,但是你打败了我:)但为什么不打算(std :: pair <int,float> p(0,0.0f); p.first <10; p.first ++,p.second = 2*p.first){...}? (3认同)
  • 为这美丽的代码腹泻+1(这是OP要求的) (3认同)

Joh*_*itb 10

这是一个使用boost预处理器的版本(这只是为了好玩.对于现实世界的答案,请参阅上面的@ kitchen的一个):

FOR((int i = 0)(int j = 0.0), i < 10, (i += 1, j = 2 * i)) { 

}
Run Code Online (Sandbox Code Playgroud)

第一部分指定了一系列声明:(a)(b)....稍后声明的变量可以引用在它们之前声明的变量.第二和第三部分和往常一样.在第二和第三部分中出现逗号的地方,括号可用于防止它们分隔宏参数.

我知道有两个技巧用于声明变量,这些变量稍后在宏外部添加的复合语句中可见.第一个使用条件,如if:

if(int k = 0) ; else COMPOUND_STATEMENT
Run Code Online (Sandbox Code Playgroud)

然后k是可见的.当然,它总是要评估false.所以它不能被我们使用.另一个背景是这个:

for(int k = 0; ...; ...) COMPOUND_STATEMENT
Run Code Online (Sandbox Code Playgroud)

这就是我将在这里使用的内容.我们必须注意只进行一次迭代COMPOUND_STATEMENT.for执行增量和条件检查的实际循环必须在最后,因此附加的复合语句附带到它.

#include <boost/preprocessor.hpp>
#include <iostream>

#define EMIT_DEC_(R,D,DEC) \
    for(DEC; !_k; ) 

#define FOR(DECS, COND, INC) \
    if(bool _k = false) ; else \
      BOOST_PP_SEQ_FOR_EACH(EMIT_DEC_, DECS, DECS) \
        for(_k = true; COND; INC)

int main() {
    FOR((int i = 0)(float j = 0.0f), i < 10, (i += 1, j = 2 * i)) {
        std::cout << j << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

它创建了一堆for语句,每个语句都嵌套在另一个语句中.它扩展为:

if(bool _k = false) ; else
  for(int i = 0; !_k; )
    for(float j = 0.0f; !_k; )
      for(_k = true; i < 10; (i += 1, j = 2 * i)) {
        std::cout << j << std::endl;
      }
Run Code Online (Sandbox Code Playgroud)


Pau*_*lin 8

{
  int i = 0;
  float j = 0.0;
  for ( ; i < 10; i += 1, j = 2*i) {
    cout << j << endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

块后面的变量"消失".


Reu*_*nen 7

这将使迭代器(或在本例中为float)在不再需要时消失:

int main() {
  // some code...

  {
    float j = 0.0;
    for (int i = 0; i < 10; i += 1, j = 2*i) {
      cout << j << endl;
    }
  }

  // more code...
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*eld 6

如果您遇到宏问题,那么有一个标准do..while技巧可以完美运行:

#define MYFOR(init, test, post, body) \
    do \
    { \
        init \
        for( ; test; post) \
            body \
    } while(0)
Run Code Online (Sandbox Code Playgroud)

使用方法如下:

MYFOR( int i = 0; float j = 0.0f; , i < 10 , (i += 1, j = 2.0f * i),
    {
         cout << j << endl;
    } );
Run Code Online (Sandbox Code Playgroud)

这很丑陋,但它可以做你想要的:宏的循环范围ij受限制do..while,并且它最后需要一个分号,所以你不会因为把它放在if/else的谓词中而被咬住声明.


Joh*_*itb 5

这个也很难看,但也提供了一些通用的方法来声明多个变量,在for循环中使用一些给定的名称和类型

int main() {
  for (struct { int i; float j; } x = { };
       x.i < 10; x.i += 1, x.j = 2 * x.i) {
    cout << x.j << endl;
  }
}
Run Code Online (Sandbox Code Playgroud)