回答:
C ++ 17:はい!構造化バインディング宣言を使用する必要があります。この構文は、gccとclangで何年もサポートされています(gcc-7とclang-4.0以降)(clang live example)。これにより、次のようにタプルを解凍できます。
for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
// ...
}
上記はあなたに与えるでしょう:
int i
に設定 1
double f
に設定 1.0
std::string s
に設定 "ab"
#include <tuple>
この種の宣言には必ず注意してください。
タイプに名前を付けたい場合tuple
はstd::string
、と同じようにすべてを入力して、内に正確なタイプを指定できます。例えば:
auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
これの特定のアプリケーションは、マップを反復して、キーと値を取得することです。
std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
// ...
}
こちらのライブ例をご覧ください
C ++ 14:type-basedを追加することで、C ++ 11(下記)と同じことができますstd::get
。だから、代わりにstd::get<0>(t)
以下の例では、あなたが持つことができますstd::get<int>(t)
。
C ++ 11:std::make_pair
これを実行できるほかstd::make_tuple
、3つ以上のオブジェクトに対しても実行できます。
for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
std::make_pair
2つの引数をで返しstd::pair
ます。要素には.first
およびを使用してアクセスできます.second
。
3つ以上のオブジェクトの場合は、 std::tuple
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
std::cout << std::get<1>(t) << std::endl; // cout Hello world
std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}
std::make_tuple
任意の数の引数のタプルを構築する可変テンプレートです(もちろん、いくつかの技術的な制限があります)。要素は、インデックスを使用してアクセスできますstd::get<INDEX>(tuple_object)
ループのための体の中ですることができます簡単にオブジェクトのエイリアス、あなたはまだ使用する必要があるものの.first
またはstd::get
ループ条件と更新式のためにのために
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
auto& i = std::get<0>(t);
auto& s = std::get<1>(t);
auto& v = std::get<2>(t);
std::cout << s << std::endl; // cout Hello world
v.push_back(i); // add counter value to the vector
}
C ++ 98およびC ++ 03のタイプに明示的に名前を付けることができstd::pair
ます。ただし、これを3つ以上のタイプに一般化する標準的な方法はありません。
for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
make_
を書き込むこともできますstd::pair(1, 1.0)
。
いいえ-しかし、技術的には回避策があります(強制されない限り、実際に使用するわけではありません)。
for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a)
{
std::cout << s.a << " " << s.b << std::endl;
}
struct { int a=0; char b='a'; } s;
不可能ですが、次のことができます。
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
または、明示的の範囲を限定f
し、i
追加のブラケットを使用しました:
{
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
}
だが...
このアプローチはダーティですが、すべてのバージョンで解決できます。
そのため、マクロ関数でよく使用します。
for(int _int=0, /* make local variable */ \
loopOnce=true; loopOnce==true; loopOnce=false)
for(char _char=0; _char<3; _char++)
{
// do anything with
// _int, _char
}
それはまたに使用することができますdeclare local variables
とinitialize global variables
。
float globalFloat;
for(int localInt=0, /* decalre local variable */ \
_=1;_;_=0)
for(globalFloat=2.f; localInt<3; localInt++) /* initialize global variable */
{
// do.
}
良い例:マクロ機能付き。
(for-loop-macroであるため、最善のアプローチを使用できない場合)
#define for_two_decl(_decl_1, _decl_2, cond, incr) \
for(_decl_1, _=1;_;_=0)\
for(_decl_2; (cond); (incr))
for_two_decl(int i=0, char c=0, i<3, i++)
{
// your body with
// i, c
}
if (A* a=nullptr);
else
for(...) // a is visible
0
またはnullptr
に初期化する場合は、このトリックを使用できます。
読みづらいのでお勧めしません。
バグのようです。
複数のforループのネストを含む別の方法については、「for ループで2つの型の変数を定義する方法はありますか?」を参照してください。Georgの「構造トリック」に対する他の方法の利点は、(1)静的および非静的ローカル変数の混合を可能にし、(2)コピー不可能な変数を可能にすることです。欠点は、読みにくく、効率が悪い可能性があることです。
マクロを定義します。
#define FOR( typeX,x,valueX, typeY,y,valueY, condition, increments) typeX x; typeY y; for(x=valueX,y=valueY;condition;increments)
FOR(int,i,0, int,f,0.0, i < 5, i++)
{
//...
}
この方法でも、変数のスコープはforループ内にないことに注意してください。
{
とを使用して別のスコープでマクロのコードをラップすることで、この制限を簡単に克服できます}
。
-std=c++0x
の形式でg ++-4.4()でfor(auto i=0, j=0.0; ...
可能ですが、この可能性はc ++ 0xテキストと一致するようにg ++-4.5で削除されました。