for ループ初期化子で 2 つの異なる型の変数を定義する方法はありますか?
-
21-08-2019 - |
質問
for ループ内で同じ型の 2 つの変数を定義できます。
int main() {
for (int i = 0, j = 0; i < 10; i += 1, j = 2*i) {
cout << j << endl;
}
}
ただし、異なる型の変数を定義することは違法です。
int main() {
for (int i = 0, float j = 0.0; i < 10; i += 1, j = 2*i) {
cout << j << endl;
}
}
これを行う方法はありますか?(使う必要ないよ i
ループ内で、ちょうど j
.)
完全にハッキングされた不明瞭な解決策を持っている場合でも、私にとっては大丈夫です。
この不自然な例では、次のようにすればよいと思います。 double
両方の変数について。一般的な答えを探しています。
変数を for 本体の外に移動することは提案しないでください。ループの直後に消える必要がある反復子であり、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; \
} \
}
次のように使用できます。
foreach(ii, collection, {
cout << ii;
}).
しかし、次のように使用されるものが必要です。
foreach(ii, collection)
cout << ii;
実行時のオーバーヘッドを導入しないでください (ただし、コンパイルが遅くなる可能性があります)。
解決
ここでブーストプリプロセッサを使用したバージョンである(これは楽しみのためだけにあるの実世界の答えについては、上記@キッチンのいずれかを参照してください。):
FOR((int i = 0)(int j = 0.0), i < 10, (i += 1, j = 2 * i)) {
}
(a)(b)...
:最初の部分は、宣言の順序を指定します。後に宣言された変数は、彼らの前に宣言された変数を参照することができます。第二および第三の部分は通常通りです。コンマは、第2および第3の部分で発生する場合、括弧は、マクロ引数を分離することを防ぐために使用することができます。
マクロの外に添加した化合物の声明で、後に表示されている変数を宣言するために使用私に知られている2つのトリックがあります。最初は次のように、条件を使用する場合:
if(int k = 0) ; else COMPOUND_STATEMENT
次にk
が見えます。当然のことながら、それは常にfalse
し評価する必要があります。だから、私たちが使用することはできません。他のコンテキストでは、このいずれかです。
for(int k = 0; ...; ...) COMPOUND_STATEMENT
それは私がここで使用するつもりだものです。私たちはCOMPOUND_STATEMENT
の1回の繰り返しを作るために見てする必要があります。インクリメントと条件のチェックを行い、実際のfor
ループが終わりに来るように持っているので、追加の複合文は、それにappertainsます。
#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;
}
}
これは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;
}
他のヒント
のいずれかを移動することをお勧めしないでください ボディのための外部の変数、 私のために、おそらく使用できません イテレータはただ消えなければなりません ループます。
あなたはこれを行うことができます:
#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;
}
まあ、それは醜いです。しかし、あなたはペアを使用することができます。
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;
}
}
{
int i = 0;
float j = 0.0;
for ( ; i < 10; i += 1, j = 2*i) {
cout << j << endl;
}
}
変数は、ブロックの後に "消える"。
これは、それはもう必要だときイテレータ(または、この場合には、フロート)が消えないようになります
int main() {
// some code...
{
float j = 0.0;
for (int i = 0; i < 10; i += 1, j = 2*i) {
cout << j << endl;
}
}
// more code...
}
、完璧に動作標準do..while
のトリックがあります:
#define MYFOR(init, test, post, body) \
do \
{ \
init \
for( ; test; post) \
body \
} while(0)
次のようにそれを使用します:
MYFOR( int i = 0; float j = 0.0f; , i < 10 , (i += 1, j = 2.0f * i),
{
cout << j << endl;
} );
これは醜いだが、それはあなたが欲しいものを行います。i
とj
の範囲はマクロからdo..while
ループによって制限され、そしてあなたがそれを置くことによってかま取得することはできませんので、それは、最後にセミコロンが必要ですもし/ else文の述語ます。
このものも醜いであるが、中にいくつかの指定された名前とタイプの複数の変数を宣言するためにもいくつかの一般的な方法を提供するためのループ
int main() {
for (struct { int i; float j; } x = { };
x.i < 10; x.i += 1, x.j = 2 * x.i) {
cout << x.j << endl;
}
}
編集:質問はもう一度変更されました。質問は今、明示的にforeachループを実装したいと考えています。最も簡単な答えます:
#include <boost/foreach.hpp>
void( std::vector<int>& v ) {
BOOST_FOREACH( int & x, v ) {
x = x*2;
}
}
のコードブロックに変数を注入する
これは答えとして意図されていないが、コードブロックに変数を注入するための、より一般的な手法を示すこと。それはいくつかのオーバーヘッドを被る場合でもOPは、使用する可能性のある定義しようとしているマクロかのように思える。の
あなたが異なるスコープで変数を定義することができる場所がいくつかあります。あなたは、任意のコードブロック内の変数を定義することができ、その寿命は、その特定のブロックの終わりになります。あなたは、forループの括弧内に変数を定義することができますし、スコープは、ループブロックになります。ブロックとその範囲は(else節を含む)の場合のようになります場合にも、内部の変数を定義することができます。
あなたは外部で作成し、その寿命のブロックのことを超えて、変数を作成せずに、コードブロックに変数を注入するために、上記のこれらのオプションを組み合わせることができます。 。具体例は、STLコンテナにのみ動作するように簡略化foreachループを(定義される呼び出しの構文は次のようになります。
void f( std::vector<int>& container )
{
INTVECTOR_FOREACH( int & x, container )
{
x = x*2;
}
}
他の言語でforeachのと同様のセマンティクスで:関数は、実際に整数ベクトル内の各値を倍にするように、Xは、コンテナ内の各要素に参照されます。
ここで簡略化されたマクロのコード
#define INTVECTOR_FOREACH( variable, container ) \
for ( std::vector<int>::iterator it = container.begin(); it!=container.end(); ++it ) \
if ( bool condition=false ) {} else \
for ( variable = *it; !condition; condition=true )
任意の容器や種類のマクロを一般化問題の文脈から外れたいくつかのメタプログラミングを必要とし、それがどのように動作するかのアイデアは(私は願っています)に従うにはあまりにも難しいことではありません。
外我々は別の の回だけ反復変数を定義する(INT&xのサンプルコード)のために実行、各反復で容器上の反復処理のため。我々は、内部ループの反復(1)の数を制御するための条件を必要とし、その条件は、 の場合と注入されます。私たちは、彼女がループの後に他の書き込みを行う場合は、ユーザーが予期しない結果を得ていないことを保証することができるように...マクロはトリッキーです失敗した場合にするために選択します。
イテレータはちょうどループの後に消えなければならないと私のために使用可能な、身体のための外側の変数のいずれかを、おそらくない移動することをお勧めしませんしてください。
あなたはまだそれを行うと、余分な変数がスコープ外に行かせるために、中括弧内全体を置くことができます。
int main()
{
{
float j = 0.0;
for (int i = 0; i < 10; i += 1, j = 2*i)
{
cout << j << endl;
}
}
// more code...
}
この方法のj
は、右ループの後にスコープ外に行くだろう。
あなたは私が考えることができる最も簡単なコードを与える必要条件ではあります:
for ( int i = 0; i < 10; ++i )
{
float f = i * 2;
std::cout << f << std::endl;
}
あなたが唯一のの値の2倍として、のF の使用私はを。寿命はループに限定されており、(少なくとも単純化された質問に、あなたが提供)フロートは、(割り当てることとまったく同じように安い)を作成するために安いです。
本当ののフロートの構築の(私は私は本当にint型ではないので、fはいずれかのフロートではないかもしれないと仮定していますが)はるかに高価な値を再割り当てするよりもあれば、他のソリューション範囲を限定するために、中括弧の余分なペアの内側にカプセル化する最良の選択肢となります。
int main() {
for (int i = 0, float j = 0.0; i < 10; i += 1, j = 2*i) {
cout << j << endl;
}
}
もしかしたら私が密なのかもしれませんが、なぜフロートを宣言する必要があるのでしょうか?ループから抜け出すときはとにかく「捨てる」だけです。右?
for(int i=0; i<10; ++i)
cout << (float)2*i << endl;
なぜjが必要なのですか?
あなたはi
、独自のタイプであると言う、あなたはちょうど、j
のうち、i
を生成する必要がありますか?簡単。 i
値を生成するj
のクラスにメンバ関数を追加し、常にそれを使用。あなたはおそらくも、あなたがしたい場合は、そのメンバ関数への呼び出しを「隠す」ためにマクロを作ることができます。 : - )
for ループの外で変数を宣言して初期化してはどうでしょうか?現在と同様に、テストと増分を行うことができます。