Использовать значение класса enum для оператора сдвига битового сдвига - PullRequest
0 голосов
/ 28 января 2019

Следующий фрагмент ...

enum class A {
        X = 0, Y = 1, Z = 2,
    };

int s = (1 << A::X);

... приводит к следующей ошибке компиляции:

error C2678: binary '<<': no operator found which takes a 
left-hand operand of type 'int' 
(or there is no acceptable conversion)

Какой самый лучший и самый чистый способ заставить этот бит-смещение работать?

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Небольшая служебная функция может помочь прояснить намерение, гарантируя при этом правильность:

#include <type_traits>

template<class Enum>
auto to_bitmask(Enum e)
{
    using type = std::underlying_type_t<Enum>;
    return 1 << type(e);
};

https://godbolt.org/z/_pp7VW

Для более общей версии c ++ 17 позволяет легко обрабатывать любое перечислениеили целочисленный тип:

template<class Enum>
constexpr auto to_bitmask(Enum e)
{
    static_assert(std::is_integral<Enum>() || std::is_enum<Enum>());

    if constexpr (std::is_enum<Enum>())
    {
        using type = std::underlying_type_t<Enum>;
        return 1 << type(e);
    }
    else 
    {
        return 1 << e;
    }
}
0 голосов
/ 28 января 2019

Следующий способ работы.Cmd: g ++ test.cc

#include <iostream>
int main(){
    enum A {
        X = 0, Y , Z
    };

    int s = (1 << Y);
    std::cout <<"s = "<< s << std::endl;
}
0 голосов
/ 28 января 2019

Перечисление в определенной области строго типизировано.Вам нужно явно определить операторы, которые вы хотите поддерживать, поскольку неявное преобразование в целое число не может сделать жизнеспособным встроенный оператор.

Если вы хотите включить неявное преобразование в int, не даваявверх по области видимости идентификатора вы можете использовать перечисление в "старом стиле".То есть вместо этого оберните его в тип класса:

struct A {
   enum Type {
        X = 0, Y = 1, Z = 2,
   };
};

Поскольку перечислители с незаданной областью также являются членами включающей области действия, вы можете написать еще 1 << A::X, и это даст желаемый эффект.Цена, конечно, в том, что теперь имя перечисления является более многословным A::Type.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...