C++11 class enum: operator& und operator|
-
Hallo,
C++11 hat ja strongly typed enums, will man sie jedoch als Flags einsetzten, kommt das problem das die operatoren & und | nicht definiert sind.
Ist das irgendwie elegant lösbar?Mein bisheriger ansatz (spoiler: funktioniert nicht)
template<class enum_class> struct enum_op : public enum_class { friend constexpr enum_op operator|(enum_op& a, enum_op& b) { return static_cast<enum_op> (static_cast<int>(a) | static_cast<int>(b)); } friend constexpr enum_op operator&(enum_op& a, enum_op& b) { return static_cast<enum_op> (static_cast<int>(a) & static_cast<int>(b)); } }; enum class enum_type_base {A=1,B=2,C=4}; typedef enum_op<enum_type_base> enum_type;
Funktioniert nicht. Auch die num selber abzuleiten klappt wohl nicht.
Ideen?phlox81
-
namespace enum_name { enum enum_name_t : T { foo, bar, baz }; } typedef enum_name::enum_name_t enum_name_t;
Ansonsten vielleicht was mit enable_if Operator-Templates und Type-Traits.
-
#include <iostream> enum class Enum { A = 1, B = 2, C = 4, D = 8 }; using underlying = std::underlying_type<Enum>::type; Enum operator|(const Enum& lhs, const Enum& rhs) { return static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs)); } Enum operator&(const Enum& lhs, const Enum& rhs) { return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs)); } int main(int argc, char** argv) { Enum e = Enum::A | Enum::B; std::cout << static_cast<underlying>(e) << std::endl; // 3 }
-
#include <utility> #include <type_traits> template <class T> struct has_binary_ops : std::false_type { }; template <class T> constexpr typename std::enable_if<has_binary_ops<typename std::decay<T>::type>::value, T>::type operator | (T const &left, T const &right) { typedef typename std::underlying_type<T>::type underlying; return static_cast<T>(static_cast<underlying>(left) | static_cast<underlying>(right)); } enum class file_flag : unsigned { read = 1, write = 2 }; template <> struct has_binary_ops<file_flag> : std::true_type { }; static_assert(static_cast<unsigned>(file_flag::read | file_flag::write) == 3, "Operator | is expected to work"); int main() { //works with L-Values file_flag f = file_flag::read; (f | file_flag::write); }
-
TyRoXx Lösung ist etwas flexibler, da man schnell für zusätzliche Enums die operatoren aktivieren kann, verfolgt aber das gleiche Prinzip
-
Siehe 17.5.2.1.3 Bitmask types
typedef int int_type; enum class bitmask : int_type {a=1<<0, b=1<<1, c=1<<2}; constexpr bitmask operator|(const bitmask& a, const bitmask& b){ return static_cast<bitmask>( static_cast<int_type>(a) | static_cast<int_type>(b)); } constexpr bitmask operator&(const bitmask& a, const bitmask& b){ return static_cast<bitmask>( static_cast<int_type>(a) & static_cast<int_type>(b)); } constexpr bitmask A(bitmask::a); constexpr bitmask B(bitmask::b); constexpr bitmask C(bitmask::c); int main(){ bitmask b1 = A | B; bitmask b2 = A & B; }