├── LICENSE ├── README.md └── include └── EnumFlags.hpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 iFarbod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpp17-enum-flag 2 | Enable bitwise operators on scoped enums. 3 | 4 | Library compiles with no warnings (`-std=c++17 -Wall -Wshadow -Wextra -Wnon-virtual-dtor -pedantic`) on Clang 14. 5 | 6 | ## Example usage 7 | 8 | ```cpp 9 | enum class TestEnum 10 | { 11 | Baz = 1 << 0, 12 | Fou = 1 << 1, 13 | Moo = 1 << 2, 14 | Foo = 1 << 3, 15 | Bar = 1 << 4, 16 | }; 17 | 18 | template <> 19 | struct zsl::EnumFlags 20 | { 21 | static constexpr bool is_flags = true; 22 | }; 23 | 24 | // ... 25 | 26 | auto main() -> int 27 | { 28 | TestEnum e{TestEnum::Baz}; 29 | auto b = zsl::EnumIsSet(e & TestEnum::Baz); 30 | std::cout << (b ? "true" : "false"); 31 | 32 | e = TestEnum::Foo | TestEnum::Baz; 33 | return 0; 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /include/EnumFlags.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2022 iFarbod and other contributors. All Rights Reserved. 2 | // 3 | // SPDX-License-Identifier: MIT 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace zsl 10 | { 11 | 12 | // Example usage: 13 | // template <> 14 | // struct zsl::EnumFlags 15 | // { 16 | // static constexpr bool is_flags = true; 17 | // }; 18 | 19 | template 20 | struct EnumFlags 21 | { 22 | }; 23 | 24 | template 25 | struct HasIsFlags : std::false_type 26 | { 27 | }; 28 | 29 | template 30 | struct HasIsFlags::is_flags)>> 31 | : std::bool_constant::is_flags)>>> 32 | { 33 | }; 34 | 35 | template 36 | constexpr auto IsFlagsEnum() -> bool 37 | { 38 | if constexpr (HasIsFlags::value) 39 | { 40 | return EnumFlags::is_flags; 41 | } 42 | return false; 43 | } 44 | 45 | template 46 | inline constexpr bool IsFlagsV = IsFlagsEnum(); 47 | 48 | template 49 | constexpr auto EnumIsSet(T e) -> std::enable_if_t && zsl::IsFlagsV, bool> 50 | { 51 | return static_cast(e); 52 | } 53 | 54 | } // namespace zsl 55 | 56 | template && zsl::IsFlagsV, int> = 0> 57 | constexpr auto operator&(T lhs, T rhs) -> T 58 | { 59 | using UnderlyingType = std::underlying_type_t; 60 | return static_cast(static_cast(lhs) & static_cast(rhs)); 61 | } 62 | 63 | template && zsl::IsFlagsV, int> = 0> 64 | constexpr auto operator|(T lhs, T rhs) -> T 65 | { 66 | using UnderlyingType = std::underlying_type_t; 67 | return static_cast(static_cast(lhs) | static_cast(rhs)); 68 | } 69 | 70 | template && zsl::IsFlagsV, int> = 0> 71 | constexpr auto operator^(T lhs, T rhs) -> T 72 | { 73 | using UnderlyingType = std::underlying_type_t; 74 | return static_cast(static_cast(lhs) | static_cast(rhs)); 75 | } 76 | 77 | template && zsl::IsFlagsV, int> = 0> 78 | constexpr auto operator~(T lhs) -> T 79 | { 80 | using UnderlyingType = std::underlying_type_t; 81 | return static_cast(~static_cast(lhs)); 82 | } 83 | 84 | template && zsl::IsFlagsV, int> = 0> 85 | constexpr auto operator&=(T lhs, T rhs) -> T 86 | { 87 | using UnderlyingType = std::underlying_type_t; 88 | return lhs = static_cast(static_cast(lhs) & static_cast(rhs)); 89 | } 90 | 91 | template && zsl::IsFlagsV, int> = 0> 92 | constexpr auto operator|=(T lhs, T rhs) -> T 93 | { 94 | using UnderlyingType = std::underlying_type_t; 95 | return lhs = static_cast(static_cast(lhs) | static_cast(rhs)); 96 | } 97 | 98 | template && zsl::IsFlagsV, int> = 0> 99 | constexpr auto operator^=(T lhs, T rhs) -> T 100 | { 101 | using UnderlyingType = std::underlying_type_t; 102 | return lhs = static_cast(static_cast(lhs) ^ static_cast(rhs)); 103 | } 104 | --------------------------------------------------------------------------------