Restricting an enum class template to a labeled type

Viewed 114

I want to use enum class <NAME> as a bitmask. I've written the following concept restricting the use of the templates for only Enum classes:

template <class E>
concept Enumeration =
    std::is_enum_v<E> &&
    !std::convertible_to<E, std::underlying_type<E>>;

Now using this concept to make an add template:

template <Enumeration Element>
inline constexpr Element operator + (Element lhs, Element rhs) {
    using T = std::underlying_type_t<Element>;
    return static_cast<Element>(static_cast<T>(lhs) | static_cast<T>(rhs));
}

But this pollutes all enum classes with bitmask operators. I want to restrict the usage when the enum classes are defined like this:

enum class An_Enum : Bitmask_t<std::size_t> {
};

Where Bitmask_t is a restricted template like this:

template <class T>
concept Bitmask_t = std::integral<T>;

How do I enforce this restriction in my Enumeration concept? Is there a better approach to achieving this template constraint?

1 Answers

You can tag arbitrary types with arbitrary tags in many ways. Here is one that is visually pleasing:

using Conceptually = void;

enum class MyBitmask : ...;
Conceptually IsBitmask(MyBitmask);     // no need to define the function

enum class NotABitmask : ...;
// nothing

Then use it in templates:

template <typename T> concept Bitmask = requires(T t) { IsBitmask(t); }; 

template <Bitmask T> T operator+(T a, T b) ...
Related