cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
91 stars 0 forks source link

Автоматические BitmaskType для scoped enum #569

Open bibmaster opened 1 year ago

bibmaster commented 1 year ago

Добавить маркер bitmask для scoped enum.

В стандарте есть различные scoped enum удовлетворяющие требованиям BitmaskType. Но реализация этих требований выливается в большое количество boilerplate кода. Примеры: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/fs_fwd.h#L165 https://github.com/microsoft/STL/blob/ed8150e099f6124c50dd4f002cd2ab8c429a81e3/stl/inc/type_traits#L2270

Предлагается переложить эту работу на компилятор, явно указав допустимость выполненения битовых операций со значениями enum. Во избежание добавления новых ключевых слов можно расширить enum-key. Сейчас это one of enum, enum class, or enum struct, добавить enum union

enum union perms

При этом предполагается что операции вида Enum::x <op> Enum::y будут эквивалентны следующему коду:

static_cast<Enum>(static_cast<undelying_type_t<Enum>>(x) <op> static_cast<underlying_type_t<Enum>>(y))

Вторая проблема с использованием scoped enum в качестве bitmask это проверки на 0. Пример из gcc:

namespace
{
  template<typename Bitmask>
    inline bool
    is_set(Bitmask obj, Bitmask bits)
    {
      return (obj & bits) != Bitmask::none;
    }
}

Предлагается для значений bitmask enum использовать правила explicit bool conversion аналогичные таковым для соотвествующих underlying type.

// Было
if(is_set(mask, options::x))
if((mask & options::x) != options::none)

// Стало
if(mask & options::x)

Дополнительно можно добавить concept Bitmask и функцию проверки

template<Bitmask T> constexpr bool std::is_set(T mask, T bits)

bool x_enabled = std::is_set(mask, option::x);
kin4stat commented 1 year ago

Проблема в том, что атрибуты - опциональны. Тут нужен кейворд, или что-то подобное

bibmaster commented 1 year ago

Проблема в том, что атрибуты - опциональны. Тут нужен кейворд, или что-то подобное

Ok, пусть будет например enum union вместо enum class

vtopunov commented 1 year ago

А может лучше Bitmask operator & (Bitmask, Bitmask) = default; и constexpr bool is_set(Bitmask obj, Bitmask bits) noexcept { return (obj & bits) == bits; }

bibmaster commented 1 year ago

А может лучше Bitmask operator & (Bitmask, Bitmask) = default; и constexpr bool is_set(Bitmask obj, Bitmask bits) noexcept { return (obj & bits) == bits; }

Ну так то можно это всё и в макрос завернуть, но лучший код тот которого нет. С теми же default всё равно же придется расписать &,|,^,~. А с contextual bool conversion вообще никак не решить вручную. Ну и компиляторам легче, не нужно вообще ничего искать, сам тип содержит информацию о возможности битовых операций.