OSDN Git Service

Merge pull request #1829 from sikabane-works/feature/refactor-rbe_type
[hengbandforosx/hengbandosx.git] / src / util / enum-range.h
1 #pragma once
2
3 #include <type_traits>
4
5 /*!
6  * @brief enum もしくは enum class の列挙値の範囲を扱うクラス
7  *
8  * @tparam EnumType 対象となる列挙型(enum もしくは enum class)
9  */
10 template <typename EnumType>
11 class EnumRange {
12     static_assert(std::is_enum_v<EnumType>);
13
14 public:
15     /*!
16      * @brief 列挙値の範囲のイテレータクラス
17      */
18     class iterator {
19     public:
20         /*!
21          * @brief 引数で与えた列挙値を指すイテレータオブジェクトを生成する
22          *
23          * @param val イテレータオブジェクトが指す列挙値
24          */
25         constexpr iterator(EnumType val) noexcept
26             : index(std::underlying_type_t<EnumType>(val))
27         {
28         }
29
30         /*!
31          * @brief イテレータが指している列挙値を取得する
32          *
33          * @return イテレータが指している列挙値
34          */
35         constexpr EnumType operator*() const noexcept
36         {
37             return static_cast<EnumType>(index);
38         }
39
40         /*!
41          * @brief イテレータをインクリメントする
42          *
43          * @return *this の参照
44          */
45         iterator &operator++() noexcept
46         {
47             ++index;
48             return *this;
49         }
50
51         /*!
52          * @brief 2つのイテレータが指している列挙値が等しいかどうか調べる
53          *
54          * @param other 比較対象となるイテレータ
55          * @return 2つのイテレータが指している列挙値が等しければ true、そうでなければ false
56          */
57         constexpr bool operator==(const iterator &other) const noexcept
58         {
59             return index == other.index;
60         }
61
62         /*!
63          * @brief 2つのイテレータが指している列挙値が等しくないかどうか調べる
64          *
65          * @param other 比較対象となるイテレータ
66          * @return 2つのイテレータが指している列挙値が等しくなければ true、そうでなければ false
67          */
68         constexpr bool operator!=(const iterator &other) const noexcept
69         {
70             return !this->operator==(other);
71         }
72
73     private:
74         //! 現在イテレータが指している列挙値の基底型における整数値
75         std::underlying_type_t<EnumType> index;
76     };
77
78     /*!
79      * @brief 引数で与えた範囲の EnumRange クラスのオブジェクトを生成する
80      * @details 生成する範囲はfirstからlastまで(lastを含む)。
81      * 範囲の最終値+1の列挙値が存在しない場合を考慮し、半開区間ではなく閉区間で範囲を指定する。
82      * 範囲のイテレーションは基底型の整数値をインクリメントする事によって行うので、
83      * first から last までの間の整数値が飛んでいる場合、その部分は具体的な定義の無い列挙値がイテレートされる。
84      * @param first 範囲の最初となる列挙値
85      * @param last 範囲の最後となる列挙値(lastも含む)
86      */
87     constexpr EnumRange(EnumType first, EnumType last) noexcept
88         : begin_val(first)
89         , end_val(static_cast<EnumType>(std::underlying_type_t<EnumType>(last) + 1))
90     {
91     }
92
93     /*!
94      * @brief 範囲の最初の列挙値を指すイテレータを取得する
95      *
96      * @return 範囲の最初の列挙値を指すイテレータ
97      */
98     constexpr iterator begin() const noexcept
99     {
100         return iterator(begin_val);
101     }
102
103     /*!
104      * @brief 範囲の最後の列挙値の次の値を指すイテレータを取得する
105      *
106      * @return 範囲の最後の列挙値の次の値を指すイテレータ
107      */
108     constexpr iterator end() const noexcept
109     {
110         return iterator(end_val);
111     }
112
113 private:
114     EnumType begin_val;
115     EnumType end_val;
116 };