From c49afd9a6706ed7da4ee0b1e6c43d2029b88fb72 Mon Sep 17 00:00:00 2001 From: Habu Date: Fri, 2 Jun 2023 19:56:40 +0900 Subject: [PATCH] =?utf8?q?[Update]=20FlagGroup=E3=81=AE=E3=82=B3=E3=83=B3?= =?utf8?q?=E3=82=B9=E3=83=88=E3=83=A9=E3=82=AF=E3=82=BF=E3=81=AEconstexpr?= =?utf8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit FlagGroupクラスで保持するフラグ列挙値の最大値がunsigned long long型の ビットサイズ未満の場合、std::bitsetのunsigned long long型を引数に受け取 るconstexprコンストラクタを使用することでFlagGroupのコンストラクタも constexprにする。 --- src/util/flag-group.h | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/util/flag-group.h b/src/util/flag-group.h index 4c7972917..e476f64bd 100644 --- a/src/util/flag-group.h +++ b/src/util/flag-group.h @@ -62,6 +62,16 @@ void write_bitset(const std::bitset &bs, Func wr_byte_func, size_t } } +template +constexpr unsigned long long calc_bitset_val(InputIter first, InputIter last) noexcept +{ + auto result = 0ULL; + for (; first != last; ++first) { + result |= 1ULL << static_cast(*first); + } + return result; +} + } /** @@ -94,7 +104,7 @@ public: * * すべてのフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する */ - FlagGroup() = default; + constexpr FlagGroup() = default; /** * @brief FlagGroupクラスのコンストラクタ @@ -104,7 +114,7 @@ public: * * @param il ONの状態で生成するフラグを指定した initializer_list */ - FlagGroup(std::initializer_list il) + constexpr FlagGroup(std::initializer_list il) : FlagGroup(il.begin(), il.end()) { } @@ -117,7 +127,7 @@ public: * * @param range 範囲を示すEnumRangeクラスのオブジェクト */ - FlagGroup(const EnumRange &range) + constexpr FlagGroup(const EnumRange &range) : FlagGroup(range.begin(), range.end()) { } @@ -128,11 +138,42 @@ public: * 入力イテレータで指定した範囲のリストに含まれるフラグがON、 * それ以外のフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する * + * FLAG_TYPE_MAXがunsigned long longのビットサイズ以下の場合、 + * unsigned long longの値を引数に取るstd::bitsetのconstexpr化された + * コンストラクタが使用できるので、FlagGroupクラスでも + * constexprコンストラクタとしてこちらを選択する。 + * + * @tparam InputIter 入力イテレータの型 + * @param first 範囲の開始位置を示す入力イテレータ + * @param last 範囲の終了位置を示す入力イテレータ + */ + template InputIter> + requires(FLAG_TYPE_MAX <= sizeof(unsigned long long) * 8) + constexpr FlagGroup(InputIter first, InputIter last) + : bs_(flag_group::detail::calc_bitset_val(first, last)) + { + } + + /** + * @brief FlagGroupクラスのコンストラクタ + * + * 入力イテレータで指定した範囲のリストに含まれるフラグがON、 + * それ以外のフラグがOFFの状態のFlagGroupクラスのインスタンスを生成する + * + * FLAG_TYPE_MAXがunsigned long longのビットサイズより大きい場合、 + * C++20の範囲ではstd::bitsetをconstexprコンストラクタで初期化することは + * できないため、constexprではない通常のコンストラクタとしてこちらを選択する。 + * + * @todo C++23以降であればstd::bitsetの多くのメンバ関数がconstepxr化されているので + * FLAG_TYPE_MAXがunsigned long longのビットサイズより大きくてもconstexpr化が + * 可能になると思われる。 + * * @tparam InputIter 入力イテレータの型 * @param first 範囲の開始位置を示す入力イテレータ * @param last 範囲の終了位置を示す入力イテレータ */ template InputIter> + requires(FLAG_TYPE_MAX > sizeof(unsigned long long) * 8) FlagGroup(InputIter first, InputIter last) { for (; first != last; ++first) { -- 2.11.0