web-dev-qa-db-ja.com

forループの短縮形-C ++(11)の構文糖

実際、これらは2つの関連する質問です。

次の形式の範囲ベースのforループ用のC++ 11に新しい構文があることを知っています。

//v is some container
for (auto &i: v){
   // Do something with i
}

最初の質問:このループのどの反復であるかをどのように推測できますか? (位置jでベクトルを値jで埋めたいとしましょう)。

2番目の質問:フォームのループを記述する他の方法があるかどうかを知りたい

for (int i=0; i<100; i++) { ... }

この書き方は少し面倒だと思うし、これを頻繁にやるので、もっと簡潔な構文が欲しいです。線に沿って何か:

for(i in [0..99]){ ... }

素晴らしいことだ。

どちらの質問についても、追加のライブラリを使用する必要はありません。

18
dingalapadum

最初の答え:そうではありません。単純な目的のために単純な構造を使用しました。より複雑なニーズがある場合は、より複雑なものが必要になります。

2番目の答え:連続した整数値を生成するイテレータ型と、それらの範囲を提供する「コンテナ」型を作成できます。あなたが自分でそれをする正当な理由がない限り、Boostには そのようなこと があります:

#include <boost/range/irange.hpp>

for (int i : boost::irange(0,100)) {
    // i goes from 0 to 99 inclusive
}
21
Mike Seymour

これを使って:

size_t pos = 0;
for (auto& i : v) {
    i = pos;
    ++pos;
}

Boost は良いですが、普遍的に受け入れられていません。)

15
Peter K

最初の質問に対する答えは非常に簡単です。反復カウントが必要な場合は、反復カウントを抽象化する構文構造を使用しないでください。範囲ベースのループではなく、通常のforループを使用してください。

2番目の質問については、標準ライブラリには現在何も存在しないと思いますが、 boost::irange そのため:

for (int i : boost::irange(0, 100))
11
Angew

2番目の質問- Boost が重すぎる場合は、常にこのライブラリを使用できます。

for(auto i : range(10, 15)) { cout << i << '\n'; }は_10 11 12 13 14_を出力します

for(auto i : range(20, 30, 2)) { cout << i << '\n'; }は_20 22 24 26 28_を出力します

倍精度やその他の数値型もサポートされています。

他のPython反復ツールがあり、ヘッダーのみです。

4
onqtam

Boost.Rangeを使用すると、これらの両方を実行できます。 http://boost.org/libs/range

簡潔にするために(そして、少しスパイスを入れるために、boost::irangeは既に単独でデモンストレーションされています)、これらの機能が連携して動作することを示すサンプルコードを次に示します。

// boost::adaptors::indexed
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/adaptors/reference/indexed.html
#include <boost/range/adaptor/indexed.hpp>

// boost::irange
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/ranges/irange.html
#include <boost/range/irange.hpp>

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> input{11, 22, 33, 44, 55};
    std::cout << "boost::adaptors::indexed" << '\n';
    for (const auto & element : input | boost::adaptors::indexed())
    {
        std::cout << "Value = " << element.value()
                  << " Index = " << element.index()
                  << '\n';
    }

    endl(std::cout);

    std::cout << "boost::irange" << '\n';
    for (const auto & element : boost::irange(0, 5) | boost::adaptors::indexed(100))
    {
        std::cout << "Value = " << element.value()
                  << " Index = " << element.index()
                  << '\n';
    }

    return 0;
}

サンプル出力:

boost::adaptors::indexed
Value = 11 Index = 0
Value = 22 Index = 1
Value = 33 Index = 2
Value = 44 Index = 3
Value = 55 Index = 4

boost::irange
Value = 0 Index = 100
Value = 1 Index = 101
Value = 2 Index = 102
Value = 3 Index = 103
Value = 4 Index = 104
3
Matt

2番目の質問:

別の方法もありますが、私は使用も推奨もしませんにします。ただし、テストをすばやく設定するには、次のように記述できます。

ライブラリを使用したくなく、範囲の上限を指定するだけでよい場合は、次のように記述できます。

for (auto i:vector<bool>(10)) {
    cout << "x";
}

これにより、初期化されていない値を持つサイズ10のブールベクトルが作成されます。 iを使用してこれらの初期化された値をループします((not使用i)10回 "x"を出力します。

2
Stuck

vがベクトル(または任意のstd連続コンテナ)の場合、

for(auto& x : v ) {
  size_t i = &x-v.data();
  x = i;
}

i番目のエントリに値iを設定します。

カウントする出力反復子は、かなり簡単に記述できます。 Boost には1つがあり、irangeと呼ばれる生成しやすい範囲があります。

コンテナのインデックスの抽出は比較的簡単です。 indexesという関数を作成しました。この関数は、コンテナーまたは整数の範囲を取り、問題の範囲でランダムな出力反復子を生成します。

それはあなたに与えます:

for (size_t i : indexes(v) ) {
  v[i] = i;
}

Boostには、おそらく同等のコンテナからインデックスへの範囲関数があります。

両方が必要で、作業をしたくない場合は、ジッパーを作成できます。

for( auto z : Zip( v, indexes(v) ) ) {
  auto& x = std::get<0>(z);
  size_t i = std::get<1>(z);
  x = i;
}

ここで、Zipは2つ以上の反復可能な範囲(またはコンテナー)を取り、要素へのiterator_traits<It>::referencesのタプルの範囲ビューを生成します。

Boost Zipイテレータは次のとおりです: http://www.boost.org/doc/libs/1_41_0/libs/iterator/doc/Zip_iterator.html - -おそらく、上記のZip関数のような構文を処理するBoost Zip範囲があります。

2番目の質問では、最新のVisual Studioバージョンを使用している場合は、「if」と入力してから Tab、 Tab、そして Tab 初期値、ステップアップなどを入力します。

0
Sheen