1. ホーム
  2. c++

[解決済み] enumクラスでRange-Based Forを可能にする?

2023-05-08 20:02:34

質問

のすべてのメンバーをループするコードを繰り返し書いています。 enum class .

for ループと比べると、非常に扱いにくい印象を受けます。 range-based for .

C++11 の新機能を利用して、現在使用している for ループの冗長性を削減する方法はありますか?

現在のコードで改善したいもの

enum class COLOR
{
    Blue,
    Red,
    Green,
    Purple,
    First=Blue,
    Last=Purple
};

inline COLOR operator++( COLOR& x ) { return x = (COLOR)(((int)(x) + 1)); }

int main(int argc, char** argv)
{
  // any way to improve the next line with range-based for?
  for( COLOR c=COLOR::First; c!=COLOR::Last; ++c )
  {
    // do work
  }
  return 0;
}

つまり、こんなことが出来たらいいなということです。

for( const auto& c : COLOR )
{
  // do work
}

どのように解決するのですか?

列挙自体をイテレータとして列挙を繰り返すのは良くない考えで、deft_codeさんの回答のように実際のイテレータを使用することをお勧めします。しかし、これが本当に欲しいものであるなら

COLOR operator++(COLOR& x) {
    return x = (COLOR)(std::underlying_type<COLOR>::type(x) + 1); 
}

COLOR operator*(COLOR c) {
    return c;
}

COLOR begin(COLOR r) {
    return COLOR::First;
}

COLOR end(COLOR r) {
    COLOR l=COLOR::Last;
    return ++l;
}

int main() { 
    //note the parenthesis after COLOR to make an instance
    for(const auto& c : COLOR()) {
        //do work
    }
    return 0;
}

ここで働く http://ideone.com/cyTGD8


イテレータの方では、一番簡単な方法は単純に
const COLOR COLORS[] = {COLOR::Blue, COLOR::Red, COLOR::Green, COLOR::Purple};
const COLOR (&COLORREF)[(int)COLOR::Last+1] = COLORS;

int main() { 
    for(const auto& c : COLORS) {
        //do work
    }
    return 0;
}

ここで見たように http://coliru.stacked-crooked.com/a/5d356cc91556d6ef

(個別の定義と配列の参照により、色数が配列の要素数と一致しない場合はコンパイラエラーとなります。優れた簡単な安全性チェックです)。