ideas
ideas copied to clipboard
Автоматические BitmaskType для scoped enum
Добавить маркер 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);
Проблема в том, что атрибуты - опциональны. Тут нужен кейворд, или что-то подобное
Проблема в том, что атрибуты - опциональны. Тут нужен кейворд, или что-то подобное
Ok, пусть будет например enum union вместо enum class
А может лучше Bitmask operator & (Bitmask, Bitmask) = default; и
constexpr bool is_set(Bitmask obj, Bitmask bits) noexcept { return (obj & bits) == bits; }
А может лучше
Bitmask operator & (Bitmask, Bitmask) = default;иconstexpr bool is_set(Bitmask obj, Bitmask bits) noexcept { return (obj & bits) == bits; }
Ну так то можно это всё и в макрос завернуть, но лучший код тот которого нет. С теми же default всё равно же придется расписать &,|,^,~. А с contextual bool conversion вообще никак не решить вручную. Ну и компиляторам легче, не нужно вообще ничего искать, сам тип содержит информацию о возможности битовых операций.