#ifndef slic3r_enum_bitmask_hpp_ #define slic3r_enum_bitmask_hpp_ // enum_bitmask for passing a set of attributes to a function in a type safe way. // Adapted from https://gpfault.net/posts/typesafe-bitmasks.txt.html // with hints from https://www.strikerx3.dev/cpp/2019/02/27/typesafe-enum-class-bitmasks-in-cpp.html #include namespace Slic3r { // enum_bitmasks can only be used with enums. template::value>::type> class enum_bitmask { // The type we'll use for storing the value of our bitmask should be the same as the enum's underlying type. using underlying_type = typename std::underlying_type::type; // This method helps us avoid having to explicitly set enum values to powers of two. static constexpr underlying_type mask_value(option_type o) { return 1 << static_cast(o); } // Private ctor to be used internally. explicit constexpr enum_bitmask(underlying_type o) : m_bits(o) {} public: // Default ctor creates a bitmask with no options selected. constexpr enum_bitmask() : m_bits(0) {} // Creates a enum_bitmask with just one bit set. // This ctor is intentionally non-explicit, to allow passing an options to a function: // FunctionExpectingBitmask(Options::Opt1) constexpr enum_bitmask(option_type o) : m_bits(mask_value(o)) {} // Set the bit corresponding to the given option. constexpr enum_bitmask operator|(option_type t) { return enum_bitmask(m_bits | mask_value(t)); } // Combine with another enum_bitmask of the same type. constexpr enum_bitmask operator|(enum_bitmask t) { return enum_bitmask(m_bits | t.m_bits); } // Get the value of the bit corresponding to the given option. constexpr bool operator&(option_type t) { return m_bits & mask_value(t); } constexpr bool has(option_type t) { return m_bits & mask_value(t); } private: underlying_type m_bits = 0; }; // For enabling free functions producing enum_bitmask<> type from bit operations on enums. template struct is_enum_bitmask_type { static const bool enable = false; }; #define ENABLE_ENUM_BITMASK_OPERATORS(x) template<> struct is_enum_bitmask_type { static const bool enable = true; }; template inline constexpr bool is_enum_bitmask_type_v = is_enum_bitmask_type::enable; // Creates an enum_bitmask from two options, convenient for passing of options to a function: // FunctionExpectingBitmask(Options::Opt1 | Options::Opt2 | Options::Opt3) template constexpr std::enable_if_t, enum_bitmask> operator|(option_type lhs, option_type rhs) { static_assert(std::is_enum_v); return enum_bitmask{lhs} | rhs; } template constexpr std::enable_if_t, enum_bitmask> operator|(option_type lhs, enum_bitmask rhs) { static_assert(std::is_enum_v); return enum_bitmask{lhs} | rhs; } template constexpr std::enable_if_t, enum_bitmask> only_if(bool condition, option_type opt) { static_assert(std::is_enum_v); return condition ? enum_bitmask{opt} : enum_bitmask{}; } template constexpr std::enable_if_t, enum_bitmask> only_if(bool condition, enum_bitmask opt) { static_assert(std::is_enum_v); return condition ? opt : enum_bitmask{}; } } // namespace Slic3r #endif // slic3r_enum_bitmask_hpp_