Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

753 lines
22 KiB
C++

//
// EnumClass.h
// ArticleEnumClass
//
// Created by Gabriel Aubut-Lussier on 17-08-07.
// Copyright © 2017 Gabriel Aubut-Lussier. All rights reserved.
//
#ifndef EnumClass_h
#define EnumClass_h
#include <cassert>
#include <type_traits>
template<typename T>
struct enable_enum_class_bitmask
{
static constexpr bool value = false;
};
#define enableEnumClassBitmask(T) template<> \
struct enable_enum_class_bitmask<T> \
{ \
static constexpr bool value = true; \
}
/**
* Wrapper for an enumerator that provides implicit bool conversion
*/
template <typename T>
struct enumerator
{
constexpr enumerator(const T& value) : value(value) {}
constexpr explicit operator bool() const
{
using underlying_type = typename std::underlying_type<T>::type;
return static_cast<underlying_type>(value) != 0;
}
constexpr operator T() const
{
return value;
}
T value;
};
/**
* Wrapper that differentiates combined enumerators from a single enumerator
* to provent accidental comparisons between a bitmask and a single enumerator
* using operator== or operator!=
*/
template <typename T>
struct bitmask
{
using underlying_type = typename std::underlying_type<T>::type;
constexpr bitmask(const T& value) : value(static_cast<underlying_type>(value)) {}
constexpr bitmask(const enumerator<T>& enumerator) : value(static_cast<underlying_type>(enumerator.value)) {}
constexpr explicit operator bool() const
{
return value != 0;
}
underlying_type value;
};
template<typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
make_bitmask(const T& t)
{
return bitmask<T>{t};
}
/**
* operator&(T, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const T& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
assert((static_cast<underlying_type>(lhs) & (static_cast<underlying_type>(lhs) - 1)) == 0);
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs) & static_cast<underlying_type>(rhs))};
}
/**
* operator&(enumerator<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const enumerator<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) & static_cast<underlying_type>(rhs.value))};
}
/**
* operator&(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator&(const bitmask<T>& lhs, const bitmask<T>& rhs)
{
return bitmask<T>{static_cast<T>(lhs.value & rhs.value)};
}
/**
* operator&(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(lhs.value & static_cast<underlying_type>(rhs))};
}
/**
* operator&(T, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const T& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs) & rhs.value)};
}
/**
* operator&(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(lhs.value & static_cast<underlying_type>(rhs.value))};
}
/**
* operator&(enumerator<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const enumerator<T>& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) & rhs.value)};
}
/**
* operator&(T, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const T& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs) & static_cast<underlying_type>(rhs.value))};
}
/**
* operator&(enumerator<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, enumerator<T>>::type
operator&(const enumerator<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return enumerator<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) & static_cast<underlying_type>(rhs))};
}
/**
* operator|(T, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const T& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) | static_cast<underlying_type>(rhs))};
}
/**
* operator|(enumerator<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const enumerator<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) | static_cast<underlying_type>(rhs.value))};
}
/**
* operator|(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const bitmask<T>& lhs, const bitmask<T>& rhs)
{
return bitmask<T>{static_cast<T>(lhs.value | rhs.value)};
}
/**
* operator|(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(lhs.value | static_cast<underlying_type>(rhs))};
}
/**
* operator|(T, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const T& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) | rhs.value)};
}
/**
* operator|(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(lhs.value | static_cast<underlying_type>(rhs.value))};
}
/**
* operator|(enumerator<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const enumerator<T>& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) | rhs.value)};
}
/**
* operator|(enumerator<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const enumerator<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) | static_cast<underlying_type>(rhs))};
}
/**
* operator|(T, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator|(const T& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) | static_cast<underlying_type>(rhs.value))};
}
/**
* operator^(T, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const T& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) ^ static_cast<underlying_type>(rhs))};
}
/**
* operator^(enumerator<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const enumerator<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) ^ static_cast<underlying_type>(rhs.value))};
}
/**
* operator^(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const bitmask<T>& lhs, const bitmask<T>& rhs)
{
return bitmask<T>{static_cast<T>(lhs.value ^ rhs.value)};
}
/**
* operator^(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(lhs.value ^ static_cast<underlying_type>(rhs))};
}
/**
* operator^(T, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const T& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) ^ rhs.value)};
}
/**
* operator^(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(lhs.value ^ static_cast<underlying_type>(rhs.value))};
}
/**
* operator^(enumerator<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const enumerator<T>& lhs, const bitmask<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) ^ rhs.value)};
}
/**
* operator^(enumerator<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const enumerator<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs.value) ^ static_cast<underlying_type>(rhs))};
}
/**
* operator^(T, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator^(const T& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(static_cast<underlying_type>(lhs) ^ static_cast<underlying_type>(rhs.value))};
}
/**
* operator~(T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator~(const T& value)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(~ static_cast<underlying_type>(value))};
}
/**
* operator~(enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator~(const enumerator<T>& lhs)
{
using underlying_type = typename std::underlying_type<T>::type;
return bitmask<T>{static_cast<T>(~ static_cast<underlying_type>(lhs.value))};
}
/**
* operator~(bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>>::type
operator~(const bitmask<T>& lhs)
{
return bitmask<T>{static_cast<T>(~ lhs.value)};
}
/**
* operator&=(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator&=(bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value &= static_cast<underlying_type>(rhs);
return lhs;
}
/**
* operator&=(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator&=(bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value &= static_cast<underlying_type>(rhs.value);
return lhs;
}
/**
* operator&=(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator&=(bitmask<T>& lhs, const bitmask<T>& rhs)
{
lhs.value &= rhs.value;
return lhs;
}
/**
* operator|=(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator|=(bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value |= static_cast<underlying_type>(rhs);
return lhs;
}
/**
* operator|=(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator|=(bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value |= static_cast<underlying_type>(rhs.value);
return lhs;
}
/**
* operator|=(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator|=(bitmask<T>& lhs, const bitmask<T>& rhs)
{
lhs.value |= rhs.value;
return lhs;
}
/**
* operator^=(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator^=(bitmask<T>& lhs, const T& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value ^= static_cast<underlying_type>(rhs);
return lhs;
}
/**
* operator^=(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator^=(bitmask<T>& lhs, const enumerator<T>& rhs)
{
using underlying_type = typename std::underlying_type<T>::type;
lhs.value ^= static_cast<underlying_type>(rhs.value);
return lhs;
}
/**
* operator^=(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bitmask<T>&>::type
operator^=(bitmask<T>& lhs, const bitmask<T>& rhs)
{
lhs.value ^= rhs.value;
return lhs;
}
/**
* operator==(T, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const T& lhs, const T& rhs)
{
return lhs == rhs;
}
/**
* operator==(enumerator<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const enumerator<T>& lhs, const enumerator<T>& rhs)
{
return lhs.value == rhs.value;
}
/**
* operator==(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const bitmask<T>& lhs, const bitmask<T>& rhs)
{
return lhs.value == rhs.value;
}
/**
* operator==(enumerator<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const enumerator<T>& lhs, const T& rhs)
{
return lhs.value == rhs;
}
/**
* operator==(T, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const T& lhs, const enumerator<T>& rhs)
{
return lhs == rhs.value;
}
/**
* operator==(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const bitmask<T>& lhs, const T& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator==(T, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const T& lhs, const bitmask<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator==(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const bitmask<T>& lhs, const enumerator<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator==(enumerator<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator==(const enumerator<T>& lhs, const bitmask<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator!=(T, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const T& lhs, const T& rhs)
{
return lhs != rhs;
}
/**
* operator!=(enumerator<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const enumerator<T>& lhs, const enumerator<T>& rhs)
{
return lhs.value != rhs.value;
}
/**
* operator!=(bitmask<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const bitmask<T>& lhs, const bitmask<T>& rhs)
{
return lhs.value != rhs.value;
}
/**
* operator!=(enumerator<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const enumerator<T>& lhs, const T& rhs)
{
return lhs.value != rhs;
}
/**
* operator!=(T, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const T& lhs, const enumerator<T>& rhs)
{
return lhs != rhs.value;
}
/**
* operator!=(bitmask<T>, T)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const bitmask<T>& lhs, const T& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator!=(T, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const T& lhs, const bitmask<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator!=(bitmask<T>, enumerator<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const bitmask<T>& lhs, const enumerator<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
/**
* operator!=(enumerator<T>, bitmask<T>)
*/
template <typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value && enable_enum_class_bitmask<T>::value, bool>::type
operator!=(const enumerator<T>& lhs, const bitmask<T>& rhs)
{
static_assert(!std::is_same<typename bitmask<T>::underlying_type, typename std::underlying_type<T>::type>::value, "A bitmask can't be compared to an enumerator. Use & first.");
return false;
}
#endif /* EnumClass_h */