// __ __ _ ______ _____ // | \/ | (_) | ____| / ____|_ _ // | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_ // | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _| // | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| // |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| // __/ | https://github.com/Neargye/magic_enum // |___/ version 0.8.2 // // Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2019 - 2022 Daniil Goncharov . // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #ifndef NEARGYE_MAGIC_ENUM_FUSE_HPP #define NEARGYE_MAGIC_ENUM_FUSE_HPP #include "magic_enum.hpp" namespace magic_enum { namespace detail { template constexpr optional fuse_one_enum(optional hash, E value) noexcept { if (hash) { if (const auto index = enum_index(value)) { return (*hash << log2(enum_count() + 1)) | *index; } } return {}; } template constexpr optional fuse_enum(E value) noexcept { return fuse_one_enum(0, value); } template constexpr optional fuse_enum(E head, Es... tail) noexcept { return fuse_one_enum(fuse_enum(tail...), head); } template constexpr auto typesafe_fuse_enum(Es... values) noexcept { enum class enum_fuse_t : std::uintmax_t; const auto fuse = fuse_enum(values...); if (fuse) { return optional{static_cast(*fuse)}; } return optional{}; } } // namespace magic_enum::detail // Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements. template [[nodiscard]] constexpr auto enum_fuse(Es... values) noexcept { static_assert((std::is_enum_v> && ...), "magic_enum::enum_fuse requires enum type."); static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 values."); static_assert((detail::log2(enum_count>() + 1) + ...) <= (sizeof(std::uintmax_t) * 8), "magic_enum::enum_fuse does not work for large enums"); #if defined(MAGIC_ENUM_NO_TYPESAFE_ENUM_FUSE) const auto fuse = detail::fuse_enum...>(values...); #else const auto fuse = detail::typesafe_fuse_enum...>(values...); #endif return assert(fuse), fuse; } } // namespace magic_enum #endif // NEARGYE_MAGIC_ENUM_FUSE_HPP