шаблонный оператор для строго типизированных перечислений - PullRequest
0 голосов
/ 11 января 2019

У меня есть два перечисления с базовым типом uint32_t. и мне нужен оператор constexpr OR для них, потому что некоторые из членов должны состоять из результата OR других членов. Я хотел избежать реализации оператора дважды или более раз.

Итак, я попытался использовать шаблон для достижения этого.

    template <enum class E>
    constexpr uint32_t operator|(const E&   left, const E& right)
    {
        return (uint32_t)left | (uint32_t)right;
    }

    template <enum class E>
    constexpr uint32_t operator|(const uint32_t& left, const E& right)
    {
        return left | (uint32_t)right;
    }

    enum class U32Enum1 : uint32_t { 
        OtherMember1 = 0x01L,
        OtherMember2 = 0x02L,
        SomeOfMember = OtherMember1 | OtherMember2 // Not work
    }

    enum class U32Enum2 : uint32_t {
        OtherMember1 = 0x01L,
        OtherMember2 = 0x02L,
        SomeOfMember = OtherMember1 | OtherMember2 // Not work    
    }

Однако, это не сработает, и компилятор дал мне сообщение, что нет соответствующих операндов для оператора |. Как мне это сделать?

1 Ответ

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

template <enum class E> не очень хороший синтаксис, вы могли бы сделать вместо этого:

template <class E, std::enable_if_t<std::is_enum<E>::value, int> = 0>
constexpr E operator|(const E&   left, const E& right)
{
    return static_cast<E>((uint32_t)left | (uint32_t)right);
}

и использование базового типа еще лучше:

template <class E, std::enable_if_t<std::is_enum<E>::value, int> = 0>
constexpr E operator|(const E&   left, const E& right)
{
    using T = typename std::underlying_type<E>::type;
    return static_cast<E>(static_cast<T>(left) | static_cast<T>(right));
}
...