1*6881a400Schristos /* Copyright (C) 2015-2023 Free Software Foundation, Inc. 27d62b00eSchristos 37d62b00eSchristos This file is part of GDB. 47d62b00eSchristos 57d62b00eSchristos This program is free software; you can redistribute it and/or modify 67d62b00eSchristos it under the terms of the GNU General Public License as published by 77d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 87d62b00eSchristos (at your option) any later version. 97d62b00eSchristos 107d62b00eSchristos This program is distributed in the hope that it will be useful, 117d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 127d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137d62b00eSchristos GNU General Public License for more details. 147d62b00eSchristos 157d62b00eSchristos You should have received a copy of the GNU General Public License 167d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 177d62b00eSchristos 187d62b00eSchristos #ifndef COMMON_ENUM_FLAGS_H 197d62b00eSchristos #define COMMON_ENUM_FLAGS_H 207d62b00eSchristos 21*6881a400Schristos #include "traits.h" 22*6881a400Schristos 237d62b00eSchristos /* Type-safe wrapper for enum flags. enum flags are enums where the 247d62b00eSchristos values are bits that are meant to be ORed together. 257d62b00eSchristos 267d62b00eSchristos This allows writing code like the below, while with raw enums this 277d62b00eSchristos would fail to compile without casts to enum type at the assignments 287d62b00eSchristos to 'f': 297d62b00eSchristos 307d62b00eSchristos enum some_flag 317d62b00eSchristos { 327d62b00eSchristos flag_val1 = 1 << 1, 337d62b00eSchristos flag_val2 = 1 << 2, 347d62b00eSchristos flag_val3 = 1 << 3, 357d62b00eSchristos flag_val4 = 1 << 4, 367d62b00eSchristos }; 377d62b00eSchristos DEF_ENUM_FLAGS_TYPE(enum some_flag, some_flags); 387d62b00eSchristos 397d62b00eSchristos some_flags f = flag_val1 | flag_val2; 407d62b00eSchristos f |= flag_val3; 417d62b00eSchristos 427d62b00eSchristos It's also possible to assign literal zero to an enum flags variable 437d62b00eSchristos (meaning, no flags), dispensing adding an awkward explicit "no 447d62b00eSchristos value" value to the enumeration. For example: 457d62b00eSchristos 467d62b00eSchristos some_flags f = 0; 477d62b00eSchristos f |= flag_val3 | flag_val4; 487d62b00eSchristos 497d62b00eSchristos Note that literal integers other than zero fail to compile: 507d62b00eSchristos 517d62b00eSchristos some_flags f = 1; // error 527d62b00eSchristos */ 537d62b00eSchristos 547d62b00eSchristos #ifdef __cplusplus 557d62b00eSchristos 56*6881a400Schristos /* Use this to mark an enum as flags enum. It defines FLAGS_TYPE as 577d62b00eSchristos enum_flags wrapper class for ENUM, and enables the global operator 587d62b00eSchristos overloads for ENUM. */ 597d62b00eSchristos #define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type) \ 607d62b00eSchristos typedef enum_flags<enum_type> flags_type; \ 61*6881a400Schristos void is_enum_flags_enum_type (enum_type *) 627d62b00eSchristos 63*6881a400Schristos /* To enable the global enum_flags operators for enum, declare an 64*6881a400Schristos "is_enum_flags_enum_type" overload that has exactly one parameter, 65*6881a400Schristos of type a pointer to that enum class. E.g.,: 66*6881a400Schristos 67*6881a400Schristos void is_enum_flags_enum_type (enum some_flag *); 68*6881a400Schristos 69*6881a400Schristos The function does not need to be defined, only declared. 70*6881a400Schristos DEF_ENUM_FLAGS_TYPE declares this. 71*6881a400Schristos 72*6881a400Schristos A function declaration is preferred over a traits type, because the 73*6881a400Schristos former allows calling the DEF_ENUM_FLAGS_TYPE macro inside a 74*6881a400Schristos namespace to define the corresponding enum flags type in that 75*6881a400Schristos namespace. The compiler finds the corresponding 76*6881a400Schristos is_enum_flags_enum_type function via ADL. */ 77*6881a400Schristos 78*6881a400Schristos /* Note that std::underlying_type<enum_type> is not what we want here, 79*6881a400Schristos since that returns unsigned int even when the enum decays to signed 80*6881a400Schristos int. */ 817d62b00eSchristos template<int size, bool sign> class integer_for_size { typedef void type; }; 827d62b00eSchristos template<> struct integer_for_size<1, 0> { typedef uint8_t type; }; 837d62b00eSchristos template<> struct integer_for_size<2, 0> { typedef uint16_t type; }; 847d62b00eSchristos template<> struct integer_for_size<4, 0> { typedef uint32_t type; }; 857d62b00eSchristos template<> struct integer_for_size<8, 0> { typedef uint64_t type; }; 867d62b00eSchristos template<> struct integer_for_size<1, 1> { typedef int8_t type; }; 877d62b00eSchristos template<> struct integer_for_size<2, 1> { typedef int16_t type; }; 887d62b00eSchristos template<> struct integer_for_size<4, 1> { typedef int32_t type; }; 897d62b00eSchristos template<> struct integer_for_size<8, 1> { typedef int64_t type; }; 907d62b00eSchristos 917d62b00eSchristos template<typename T> 927d62b00eSchristos struct enum_underlying_type 937d62b00eSchristos { 94*6881a400Schristos DIAGNOSTIC_PUSH 95*6881a400Schristos DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION 967d62b00eSchristos typedef typename 977d62b00eSchristos integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type 987d62b00eSchristos type; 99*6881a400Schristos DIAGNOSTIC_POP 1007d62b00eSchristos }; 1017d62b00eSchristos 102*6881a400Schristos namespace enum_flags_detail 1037d62b00eSchristos { 1047d62b00eSchristos 1057d62b00eSchristos /* Private type used to support initializing flag types with zero: 1067d62b00eSchristos 1077d62b00eSchristos foo_flags f = 0; 1087d62b00eSchristos 1097d62b00eSchristos but not other integers: 1107d62b00eSchristos 1117d62b00eSchristos foo_flags f = 1; 1127d62b00eSchristos 1137d62b00eSchristos The way this works is that we define an implicit constructor that 1147d62b00eSchristos takes a pointer to this private type. Since nothing can 1157d62b00eSchristos instantiate an object of this type, the only possible pointer to 1167d62b00eSchristos pass to the constructor is the NULL pointer, or, zero. */ 1177d62b00eSchristos struct zero_type; 1187d62b00eSchristos 119*6881a400Schristos /* gdb::Requires trait helpers. */ 120*6881a400Schristos template <typename enum_type> 121*6881a400Schristos using EnumIsUnsigned 122*6881a400Schristos = std::is_unsigned<typename enum_underlying_type<enum_type>::type>; 123*6881a400Schristos template <typename enum_type> 124*6881a400Schristos using EnumIsSigned 125*6881a400Schristos = std::is_signed<typename enum_underlying_type<enum_type>::type>; 126*6881a400Schristos 1277d62b00eSchristos } 1287d62b00eSchristos 129*6881a400Schristos template <typename E> 130*6881a400Schristos class enum_flags 131*6881a400Schristos { 132*6881a400Schristos public: 133*6881a400Schristos typedef E enum_type; 134*6881a400Schristos typedef typename enum_underlying_type<enum_type>::type underlying_type; 135*6881a400Schristos 1367d62b00eSchristos public: 1377d62b00eSchristos /* Allow default construction. */ 138*6881a400Schristos constexpr enum_flags () 1397d62b00eSchristos : m_enum_value ((enum_type) 0) 1407d62b00eSchristos {} 1417d62b00eSchristos 142*6881a400Schristos /* The default move/copy ctor/assignment do the right thing. */ 143*6881a400Schristos 1447d62b00eSchristos /* If you get an error saying these two overloads are ambiguous, 1457d62b00eSchristos then you tried to mix values of different enum types. */ 146*6881a400Schristos constexpr enum_flags (enum_type e) 1477d62b00eSchristos : m_enum_value (e) 1487d62b00eSchristos {} 149*6881a400Schristos constexpr enum_flags (enum_flags_detail::zero_type *zero) 1507d62b00eSchristos : m_enum_value ((enum_type) 0) 1517d62b00eSchristos {} 1527d62b00eSchristos 153*6881a400Schristos enum_flags &operator&= (enum_flags e) & 1547d62b00eSchristos { 155*6881a400Schristos m_enum_value = (enum_type) (m_enum_value & e.m_enum_value); 1567d62b00eSchristos return *this; 1577d62b00eSchristos } 158*6881a400Schristos enum_flags &operator|= (enum_flags e) & 1597d62b00eSchristos { 160*6881a400Schristos m_enum_value = (enum_type) (m_enum_value | e.m_enum_value); 1617d62b00eSchristos return *this; 1627d62b00eSchristos } 163*6881a400Schristos enum_flags &operator^= (enum_flags e) & 1647d62b00eSchristos { 165*6881a400Schristos m_enum_value = (enum_type) (m_enum_value ^ e.m_enum_value); 1667d62b00eSchristos return *this; 1677d62b00eSchristos } 1687d62b00eSchristos 169*6881a400Schristos /* Delete rval versions. */ 170*6881a400Schristos void operator&= (enum_flags e) && = delete; 171*6881a400Schristos void operator|= (enum_flags e) && = delete; 172*6881a400Schristos void operator^= (enum_flags e) && = delete; 173*6881a400Schristos 174*6881a400Schristos /* Like raw enums, allow conversion to the underlying type. */ 175*6881a400Schristos constexpr operator underlying_type () const 1767d62b00eSchristos { 1777d62b00eSchristos return m_enum_value; 1787d62b00eSchristos } 1797d62b00eSchristos 180*6881a400Schristos /* Get the underlying value as a raw enum. */ 181*6881a400Schristos constexpr enum_type raw () const 1827d62b00eSchristos { 183*6881a400Schristos return m_enum_value; 1847d62b00eSchristos } 185*6881a400Schristos 186*6881a400Schristos /* Binary operations involving some unrelated type (which would be a 187*6881a400Schristos bug) are implemented as non-members, and deleted. */ 1887d62b00eSchristos 1897d62b00eSchristos private: 1907d62b00eSchristos /* Stored as enum_type because GDB knows to print the bit flags 1917d62b00eSchristos neatly if the enum values look like bit flags. */ 1927d62b00eSchristos enum_type m_enum_value; 1937d62b00eSchristos }; 1947d62b00eSchristos 195*6881a400Schristos template <typename E> 196*6881a400Schristos using is_enum_flags_enum_type_t 197*6881a400Schristos = decltype (is_enum_flags_enum_type (std::declval<E *> ())); 198*6881a400Schristos 1997d62b00eSchristos /* Global operator overloads. */ 2007d62b00eSchristos 201*6881a400Schristos /* Generate binary operators. */ 2027d62b00eSchristos 203*6881a400Schristos #define ENUM_FLAGS_GEN_BINOP(OPERATOR_OP, OP) \ 204*6881a400Schristos \ 205*6881a400Schristos /* Raw enum on both LHS/RHS. Returns raw enum type. */ \ 206*6881a400Schristos template <typename enum_type, \ 207*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 208*6881a400Schristos constexpr enum_type \ 209*6881a400Schristos OPERATOR_OP (enum_type e1, enum_type e2) \ 210*6881a400Schristos { \ 211*6881a400Schristos using underlying = typename enum_flags<enum_type>::underlying_type; \ 212*6881a400Schristos return (enum_type) (underlying (e1) OP underlying (e2)); \ 213*6881a400Schristos } \ 214*6881a400Schristos \ 215*6881a400Schristos /* enum_flags on the LHS. */ \ 216*6881a400Schristos template <typename enum_type, \ 217*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 218*6881a400Schristos constexpr enum_flags<enum_type> \ 219*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> e1, enum_type e2) \ 220*6881a400Schristos { return e1.raw () OP e2; } \ 221*6881a400Schristos \ 222*6881a400Schristos /* enum_flags on the RHS. */ \ 223*6881a400Schristos template <typename enum_type, \ 224*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 225*6881a400Schristos constexpr enum_flags<enum_type> \ 226*6881a400Schristos OPERATOR_OP (enum_type e1, enum_flags<enum_type> e2) \ 227*6881a400Schristos { return e1 OP e2.raw (); } \ 228*6881a400Schristos \ 229*6881a400Schristos /* enum_flags on both LHS/RHS. */ \ 230*6881a400Schristos template <typename enum_type, \ 231*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 232*6881a400Schristos constexpr enum_flags<enum_type> \ 233*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> e1, enum_flags<enum_type> e2) \ 234*6881a400Schristos { return e1.raw () OP e2.raw (); } \ 235*6881a400Schristos \ 236*6881a400Schristos /* Delete cases involving unrelated types. */ \ 237*6881a400Schristos \ 238*6881a400Schristos template <typename enum_type, typename unrelated_type, \ 239*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 240*6881a400Schristos constexpr enum_flags<enum_type> \ 241*6881a400Schristos OPERATOR_OP (enum_type e1, unrelated_type e2) = delete; \ 242*6881a400Schristos \ 243*6881a400Schristos template <typename enum_type, typename unrelated_type, \ 244*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 245*6881a400Schristos constexpr enum_flags<enum_type> \ 246*6881a400Schristos OPERATOR_OP (unrelated_type e1, enum_type e2) = delete; \ 247*6881a400Schristos \ 248*6881a400Schristos template <typename enum_type, typename unrelated_type, \ 249*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 250*6881a400Schristos constexpr enum_flags<enum_type> \ 251*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> e1, unrelated_type e2) = delete; \ 252*6881a400Schristos \ 253*6881a400Schristos template <typename enum_type, typename unrelated_type, \ 254*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 255*6881a400Schristos constexpr enum_flags<enum_type> \ 256*6881a400Schristos OPERATOR_OP (unrelated_type e1, enum_flags<enum_type> e2) = delete; 2577d62b00eSchristos 258*6881a400Schristos /* Generate non-member compound assignment operators. Only the raw 259*6881a400Schristos enum versions are defined here. The enum_flags versions are 260*6881a400Schristos defined as member functions, simply because it's less code that 261*6881a400Schristos way. 2627d62b00eSchristos 263*6881a400Schristos Note we delete operators that would allow e.g., 264*6881a400Schristos 265*6881a400Schristos "enum_type | 1" or "enum_type1 | enum_type2" 266*6881a400Schristos 267*6881a400Schristos because that would allow a mistake like : 268*6881a400Schristos enum flags1 { F1_FLAGS1 = 1 }; 269*6881a400Schristos enum flags2 { F2_FLAGS2 = 2 }; 270*6881a400Schristos enum flags1 val; 271*6881a400Schristos switch (val) { 272*6881a400Schristos case F1_FLAGS1 | F2_FLAGS2: 273*6881a400Schristos ... 274*6881a400Schristos 275*6881a400Schristos If you really need to 'or' enumerators of different flag types, 276*6881a400Schristos cast to integer first. 277*6881a400Schristos */ 278*6881a400Schristos #define ENUM_FLAGS_GEN_COMPOUND_ASSIGN(OPERATOR_OP, OP) \ 279*6881a400Schristos /* lval reference version. */ \ 280*6881a400Schristos template <typename enum_type, \ 281*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 282*6881a400Schristos constexpr enum_type & \ 283*6881a400Schristos OPERATOR_OP (enum_type &e1, enum_type e2) \ 284*6881a400Schristos { return e1 = e1 OP e2; } \ 285*6881a400Schristos \ 286*6881a400Schristos /* rval reference version. */ \ 287*6881a400Schristos template <typename enum_type, \ 288*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 289*6881a400Schristos void \ 290*6881a400Schristos OPERATOR_OP (enum_type &&e1, enum_type e2) = delete; \ 291*6881a400Schristos \ 292*6881a400Schristos /* Delete compound assignment from unrelated types. */ \ 293*6881a400Schristos \ 294*6881a400Schristos template <typename enum_type, typename other_enum_type, \ 295*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 296*6881a400Schristos constexpr enum_type & \ 297*6881a400Schristos OPERATOR_OP (enum_type &e1, other_enum_type e2) = delete; \ 298*6881a400Schristos \ 299*6881a400Schristos template <typename enum_type, typename other_enum_type, \ 300*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> \ 301*6881a400Schristos void \ 302*6881a400Schristos OPERATOR_OP (enum_type &&e1, other_enum_type e2) = delete; 303*6881a400Schristos 304*6881a400Schristos ENUM_FLAGS_GEN_BINOP (operator|, |) 305*6881a400Schristos ENUM_FLAGS_GEN_BINOP (operator&, &) 306*6881a400Schristos ENUM_FLAGS_GEN_BINOP (operator^, ^) 307*6881a400Schristos 308*6881a400Schristos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator|=, |) 309*6881a400Schristos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator&=, &) 310*6881a400Schristos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator^=, ^) 311*6881a400Schristos 312*6881a400Schristos /* Allow comparison with enum_flags, raw enum, and integers, only. 313*6881a400Schristos The latter case allows "== 0". As side effect, it allows comparing 314*6881a400Schristos with integer variables too, but that's not a common mistake to 315*6881a400Schristos make. It's important to disable comparison with unrelated types to 316*6881a400Schristos prevent accidentally comparing with unrelated enum values, which 317*6881a400Schristos are convertible to integer, and thus coupled with enum_flags 318*6881a400Schristos convertion to underlying type too, would trigger the built-in 'bool 319*6881a400Schristos operator==(unsigned, int)' operator. */ 320*6881a400Schristos 321*6881a400Schristos #define ENUM_FLAGS_GEN_COMP(OPERATOR_OP, OP) \ 322*6881a400Schristos \ 323*6881a400Schristos /* enum_flags OP enum_flags */ \ 324*6881a400Schristos \ 325*6881a400Schristos template <typename enum_type> \ 326*6881a400Schristos constexpr bool \ 327*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> lhs, enum_flags<enum_type> rhs) \ 328*6881a400Schristos { return lhs.raw () OP rhs.raw (); } \ 329*6881a400Schristos \ 330*6881a400Schristos /* enum_flags OP other */ \ 331*6881a400Schristos \ 332*6881a400Schristos template <typename enum_type> \ 333*6881a400Schristos constexpr bool \ 334*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> lhs, enum_type rhs) \ 335*6881a400Schristos { return lhs.raw () OP rhs; } \ 336*6881a400Schristos \ 337*6881a400Schristos template <typename enum_type> \ 338*6881a400Schristos constexpr bool \ 339*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> lhs, int rhs) \ 340*6881a400Schristos { return lhs.raw () OP rhs; } \ 341*6881a400Schristos \ 342*6881a400Schristos template <typename enum_type, typename U> \ 343*6881a400Schristos constexpr bool \ 344*6881a400Schristos OPERATOR_OP (enum_flags<enum_type> lhs, U rhs) = delete; \ 345*6881a400Schristos \ 346*6881a400Schristos /* other OP enum_flags */ \ 347*6881a400Schristos \ 348*6881a400Schristos template <typename enum_type> \ 349*6881a400Schristos constexpr bool \ 350*6881a400Schristos OPERATOR_OP (enum_type lhs, enum_flags<enum_type> rhs) \ 351*6881a400Schristos { return lhs OP rhs.raw (); } \ 352*6881a400Schristos \ 353*6881a400Schristos template <typename enum_type> \ 354*6881a400Schristos constexpr bool \ 355*6881a400Schristos OPERATOR_OP (int lhs, enum_flags<enum_type> rhs) \ 356*6881a400Schristos { return lhs OP rhs.raw (); } \ 357*6881a400Schristos \ 358*6881a400Schristos template <typename enum_type, typename U> \ 359*6881a400Schristos constexpr bool \ 360*6881a400Schristos OPERATOR_OP (U lhs, enum_flags<enum_type> rhs) = delete; 361*6881a400Schristos 362*6881a400Schristos ENUM_FLAGS_GEN_COMP (operator==, ==) 363*6881a400Schristos ENUM_FLAGS_GEN_COMP (operator!=, !=) 364*6881a400Schristos 365*6881a400Schristos /* Unary operators for the raw flags enum. */ 366*6881a400Schristos 367*6881a400Schristos /* We require underlying type to be unsigned when using operator~ -- 368*6881a400Schristos if it were not unsigned, undefined behavior could result. However, 369*6881a400Schristos asserting this in the class itself would require too many 370*6881a400Schristos unnecessary changes to usages of otherwise OK enum types. */ 371*6881a400Schristos template <typename enum_type, 372*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>, 373*6881a400Schristos typename 374*6881a400Schristos = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>> 375*6881a400Schristos constexpr enum_type 3767d62b00eSchristos operator~ (enum_type e) 3777d62b00eSchristos { 378*6881a400Schristos using underlying = typename enum_flags<enum_type>::underlying_type; 379*6881a400Schristos return (enum_type) ~underlying (e); 3807d62b00eSchristos } 3817d62b00eSchristos 382*6881a400Schristos template <typename enum_type, 383*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>, 384*6881a400Schristos typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>> 385*6881a400Schristos constexpr void operator~ (enum_type e) = delete; 386*6881a400Schristos 387*6881a400Schristos template <typename enum_type, 388*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>, 389*6881a400Schristos typename 390*6881a400Schristos = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>> 391*6881a400Schristos constexpr enum_flags<enum_type> 392*6881a400Schristos operator~ (enum_flags<enum_type> e) 393*6881a400Schristos { 394*6881a400Schristos using underlying = typename enum_flags<enum_type>::underlying_type; 395*6881a400Schristos return (enum_type) ~underlying (e); 396*6881a400Schristos } 397*6881a400Schristos 398*6881a400Schristos template <typename enum_type, 399*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>, 400*6881a400Schristos typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>> 401*6881a400Schristos constexpr void operator~ (enum_flags<enum_type> e) = delete; 402*6881a400Schristos 403*6881a400Schristos /* Delete operator<< and operator>>. */ 404*6881a400Schristos 405*6881a400Schristos template <typename enum_type, typename any_type, 406*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> 407*6881a400Schristos void operator<< (const enum_type &, const any_type &) = delete; 408*6881a400Schristos 409*6881a400Schristos template <typename enum_type, typename any_type, 410*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> 411*6881a400Schristos void operator<< (const enum_flags<enum_type> &, const any_type &) = delete; 412*6881a400Schristos 413*6881a400Schristos template <typename enum_type, typename any_type, 414*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> 415*6881a400Schristos void operator>> (const enum_type &, const any_type &) = delete; 416*6881a400Schristos 417*6881a400Schristos template <typename enum_type, typename any_type, 418*6881a400Schristos typename = is_enum_flags_enum_type_t<enum_type>> 419*6881a400Schristos void operator>> (const enum_flags<enum_type> &, const any_type &) = delete; 420*6881a400Schristos 4217d62b00eSchristos #else /* __cplusplus */ 4227d62b00eSchristos 4237d62b00eSchristos /* In C, the flags type is just a typedef for the enum type. */ 4247d62b00eSchristos 4257d62b00eSchristos #define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type) \ 4267d62b00eSchristos typedef enum_type flags_type 4277d62b00eSchristos 4287d62b00eSchristos #endif /* __cplusplus */ 4297d62b00eSchristos 4307d62b00eSchristos #endif /* COMMON_ENUM_FLAGS_H */ 431