forked from pupbrained/vulkan-test
started transition to vulkan-hpp
This commit is contained in:
parent
bda0032e44
commit
12c4d95aff
|
@ -41,7 +41,6 @@
|
||||||
vulkan-extension-layer
|
vulkan-extension-layer
|
||||||
vulkan-memory-allocator
|
vulkan-memory-allocator
|
||||||
vulkan-utility-libraries
|
vulkan-utility-libraries
|
||||||
vulkan-headers
|
|
||||||
vulkan-loader
|
vulkan-loader
|
||||||
vulkan-tools
|
vulkan-tools
|
||||||
];
|
];
|
||||||
|
|
51
src/main.cpp
51
src/main.cpp
|
@ -1,3 +1,6 @@
|
||||||
|
#define VULKAN_HPP_NO_CONSTRUCTORS
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_NONE
|
#define GLFW_INCLUDE_NONE
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
@ -11,7 +14,6 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vulkan/vulkan_core.h>
|
|
||||||
|
|
||||||
#include "util/magic_enum.hpp"
|
#include "util/magic_enum.hpp"
|
||||||
#include "util/types.h"
|
#include "util/types.h"
|
||||||
|
@ -144,44 +146,41 @@ class Application {
|
||||||
if (enableValidationLayers && !checkValidationLayerSupport())
|
if (enableValidationLayers && !checkValidationLayerSupport())
|
||||||
throw std::runtime_error("validation layers requested, but not available!");
|
throw std::runtime_error("validation layers requested, but not available!");
|
||||||
|
|
||||||
VkApplicationInfo appInfo {};
|
vk::ApplicationInfo appInfo { .pApplicationName = "Hello Triangle",
|
||||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
.applicationVersion = 1,
|
||||||
appInfo.pApplicationName = "Hello Triangle";
|
.pEngineName = "No Engine",
|
||||||
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
.engineVersion = 1,
|
||||||
appInfo.pEngineName = "No Engine";
|
.apiVersion = VK_API_VERSION_1_1 };
|
||||||
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
||||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
|
||||||
|
|
||||||
VkInstanceCreateInfo createInfo {};
|
vk::InstanceCreateInfo createInfo { .pApplicationInfo = &appInfo };
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
||||||
createInfo.pApplicationInfo = &appInfo;
|
|
||||||
|
|
||||||
|
// Retrieve extensions using custom function
|
||||||
std::vector<const char*> extensions = getRequiredExtensions();
|
std::vector<const char*> extensions = getRequiredExtensions();
|
||||||
|
|
||||||
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
|
vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
|
||||||
if (enableValidationLayers) {
|
if (enableValidationLayers) {
|
||||||
createInfo.enabledLayerCount = static_cast<u32>(validationLayers.size());
|
createInfo.setEnabledLayerCount(static_cast<uint32_t>(validationLayers.size()))
|
||||||
createInfo.ppEnabledLayerNames = validationLayers.data();
|
.setPpEnabledLayerNames(validationLayers.data());
|
||||||
|
|
||||||
populateDebugMessengerCreateInfo(debugCreateInfo);
|
populateDebugMessengerCreateInfo(debugCreateInfo);
|
||||||
createInfo.pNext = static_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
|
createInfo.setPNext(&debugCreateInfo);
|
||||||
} else {
|
} else {
|
||||||
createInfo.enabledLayerCount = 0;
|
createInfo.setEnabledLayerCount(0).setPNext(nullptr);
|
||||||
|
|
||||||
createInfo.pNext = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
// Enable the portability extension and set flags
|
||||||
|
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||||
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
createInfo.setEnabledExtensionCount(static_cast<uint32_t>(extensions.size()))
|
||||||
|
.setPpEnabledExtensionNames(extensions.data())
|
||||||
createInfo.enabledExtensionCount = static_cast<u32>(extensions.size());
|
.setFlags(vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR);
|
||||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
|
||||||
|
|
||||||
for (const char* extension : extensions) std::cout << extension << std::endl;
|
for (const char* extension : extensions) std::cout << extension << std::endl;
|
||||||
|
|
||||||
if (vkCreateInstance(&createInfo, nullptr, &mInstance) != VK_SUCCESS)
|
try {
|
||||||
throw std::runtime_error("failed to create instance!");
|
mInstance = vk::createInstance(createInfo);
|
||||||
|
} catch (const vk::SystemError& err) {
|
||||||
|
throw std::runtime_error("Failed to create instance: " + std::string(err.what()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fn populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) -> void {
|
static fn populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) -> void {
|
||||||
|
|
|
@ -78,16 +78,15 @@
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'.
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'.
|
||||||
#pragma GCC diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for
|
#pragma GCC diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for
|
||||||
// char_type = char (common on Linux).
|
// char_type = char (common on Linux).
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 26495) // Variable 'static_str<N>::chars_' is uninitialized.
|
#pragma warning(disable : 26495) // Variable 'static_str<N>::chars_' is uninitialized.
|
||||||
#pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and
|
#pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and
|
||||||
// then casting the result to a 8 byte value.
|
// then casting the result to a 8 byte value.
|
||||||
#pragma warning(disable : 26451 \
|
#pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call.
|
||||||
) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call.
|
#pragma warning(disable : 4514) // Unreferenced inline function has been removed.
|
||||||
#pragma warning(disable : 4514) // Unreferenced inline function has been removed.
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Checks magic_enum compiler compatibility.
|
// Checks magic_enum compiler compatibility.
|
||||||
|
@ -163,10 +162,8 @@ namespace magic_enum {
|
||||||
static_assert(
|
static_assert(
|
||||||
[] {
|
[] {
|
||||||
if constexpr (std::is_same_v<char_type, wchar_t>) {
|
if constexpr (std::is_same_v<char_type, wchar_t>) {
|
||||||
constexpr const char c[] =
|
constexpr const char c[] = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
|
||||||
"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
|
constexpr const wchar_t wc[] = L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
|
||||||
constexpr const wchar_t wc[] =
|
|
||||||
L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
|
|
||||||
static_assert(
|
static_assert(
|
||||||
std::size(c) == std::size(wc),
|
std::size(c) == std::size(wc),
|
||||||
"magic_enum::customize identifier characters are multichars in wchar_t."
|
"magic_enum::customize identifier characters are multichars in wchar_t."
|
||||||
|
@ -209,8 +206,7 @@ namespace magic_enum {
|
||||||
class customize_t : public std::pair<detail::customize_tag, string_view> {
|
class customize_t : public std::pair<detail::customize_tag, string_view> {
|
||||||
public:
|
public:
|
||||||
constexpr customize_t(string_view srt)
|
constexpr customize_t(string_view srt)
|
||||||
: std::pair<detail::customize_tag, string_view> { detail::customize_tag::custom_tag, srt } {
|
: std::pair<detail::customize_tag, string_view> { detail::customize_tag::custom_tag, srt } {}
|
||||||
}
|
|
||||||
constexpr customize_t(const char_type* srt) : customize_t { string_view { srt } } {}
|
constexpr customize_t(const char_type* srt) : customize_t { string_view { srt } } {}
|
||||||
constexpr customize_t(detail::customize_tag tag)
|
constexpr customize_t(detail::customize_tag tag)
|
||||||
: std::pair<detail::customize_tag, string_view> { tag, string_view {} } {
|
: std::pair<detail::customize_tag, string_view> { tag, string_view {} } {
|
||||||
|
@ -249,10 +245,7 @@ namespace magic_enum {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <
|
template <auto V, typename E = std::decay_t<decltype(V)>, std::enable_if_t<std::is_enum_v<E>, int> = 0>
|
||||||
auto V,
|
|
||||||
typename E = std::decay_t<decltype(V)>,
|
|
||||||
std::enable_if_t<std::is_enum_v<E>, int> = 0>
|
|
||||||
using enum_constant = std::integral_constant<E, V>;
|
using enum_constant = std::integral_constant<E, V>;
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
|
@ -263,26 +256,22 @@ namespace magic_enum {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_is_flags<T, std::void_t<decltype(customize::enum_range<T>::is_flags)>>
|
struct has_is_flags<T, std::void_t<decltype(customize::enum_range<T>::is_flags)>>
|
||||||
: std::bool_constant<
|
: std::bool_constant<std::is_same_v<bool, std::decay_t<decltype(customize::enum_range<T>::is_flags)>>> {
|
||||||
std::is_same_v<bool, std::decay_t<decltype(customize::enum_range<T>::is_flags)>>> {};
|
};
|
||||||
|
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct range_min : std::integral_constant<int, MAGIC_ENUM_RANGE_MIN> {};
|
struct range_min : std::integral_constant<int, MAGIC_ENUM_RANGE_MIN> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct range_min<T, std::void_t<decltype(customize::enum_range<T>::min)>>
|
struct range_min<T, std::void_t<decltype(customize::enum_range<T>::min)>>
|
||||||
: std::integral_constant<
|
: std::integral_constant<decltype(customize::enum_range<T>::min), customize::enum_range<T>::min> {};
|
||||||
decltype(customize::enum_range<T>::min),
|
|
||||||
customize::enum_range<T>::min> {};
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct range_max : std::integral_constant<int, MAGIC_ENUM_RANGE_MAX> {};
|
struct range_max : std::integral_constant<int, MAGIC_ENUM_RANGE_MAX> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct range_max<T, std::void_t<decltype(customize::enum_range<T>::max)>>
|
struct range_max<T, std::void_t<decltype(customize::enum_range<T>::max)>>
|
||||||
: std::integral_constant<
|
: std::integral_constant<decltype(customize::enum_range<T>::max), customize::enum_range<T>::max> {};
|
||||||
decltype(customize::enum_range<T>::max),
|
|
||||||
customize::enum_range<T>::max> {};
|
|
||||||
|
|
||||||
struct str_view {
|
struct str_view {
|
||||||
const char* str_ = nullptr;
|
const char* str_ = nullptr;
|
||||||
|
@ -340,9 +329,7 @@ namespace magic_enum {
|
||||||
class case_insensitive {
|
class case_insensitive {
|
||||||
static constexpr char_type to_lower(char_type c) noexcept {
|
static constexpr char_type to_lower(char_type c) noexcept {
|
||||||
return (c >= static_cast<char_type>('A') && c <= static_cast<char_type>('Z'))
|
return (c >= static_cast<char_type>('A') && c <= static_cast<char_type>('Z'))
|
||||||
? static_cast<char_type>(
|
? static_cast<char_type>(c + (static_cast<char_type>('a') - static_cast<char_type>('A')))
|
||||||
c + (static_cast<char_type>('a') - static_cast<char_type>('A'))
|
|
||||||
)
|
|
||||||
: c;
|
: c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,8 +368,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
template <typename BinaryPredicate>
|
template <typename BinaryPredicate>
|
||||||
constexpr bool is_default_predicate() noexcept {
|
constexpr bool is_default_predicate() noexcept {
|
||||||
return std::
|
return std::is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<string_view::value_type>> ||
|
||||||
is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<string_view::value_type>> ||
|
|
||||||
std::is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<>>;
|
std::is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,11 +379,9 @@ namespace magic_enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BinaryPredicate>
|
template <typename BinaryPredicate>
|
||||||
constexpr bool cmp_equal(
|
constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(
|
||||||
string_view lhs,
|
is_nothrow_invocable<BinaryPredicate>()
|
||||||
string_view rhs,
|
) {
|
||||||
[[maybe_unused]] BinaryPredicate&& p
|
|
||||||
) noexcept(is_nothrow_invocable<BinaryPredicate>()) {
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
|
#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
|
||||||
// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html
|
// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html
|
||||||
// https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html
|
// https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html
|
||||||
|
@ -427,8 +411,7 @@ namespace magic_enum {
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
constexpr bool cmp_less(L lhs, R rhs) noexcept {
|
constexpr bool cmp_less(L lhs, R rhs) noexcept {
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_integral_v<L> && std::is_integral_v<R>,
|
std::is_integral_v<L> && std::is_integral_v<R>, "magic_enum::detail::cmp_less requires integral type."
|
||||||
"magic_enum::detail::cmp_less requires integral type."
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if constexpr (std::is_signed_v<L> == std::is_signed_v<R>) {
|
if constexpr (std::is_signed_v<L> == std::is_signed_v<R>) {
|
||||||
|
@ -465,8 +448,7 @@ namespace magic_enum {
|
||||||
#define MAGIC_ENUM_ARRAY_CONSTEXPR 1
|
#define MAGIC_ENUM_ARRAY_CONSTEXPR 1
|
||||||
#else
|
#else
|
||||||
template <typename T, std::size_t N, std::size_t... I>
|
template <typename T, std::size_t N, std::size_t... I>
|
||||||
constexpr std::array<std::remove_cv_t<T>, N>
|
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N], std::index_sequence<I...>) noexcept {
|
||||||
to_array(T (&a)[N], std::index_sequence<I...>) noexcept {
|
|
||||||
return { { a[I]... } };
|
return { { a[I]... } };
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -561,14 +543,11 @@ namespace magic_enum {
|
||||||
if constexpr (supported<decltype(V)>::value) {
|
if constexpr (supported<decltype(V)>::value) {
|
||||||
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
|
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
|
||||||
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
|
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
|
||||||
auto name =
|
auto name = name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
|
||||||
name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
|
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
str_view name;
|
str_view name;
|
||||||
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
|
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
|
||||||
static_assert(
|
static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
|
||||||
always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__."
|
|
||||||
);
|
|
||||||
return str_view {};
|
return str_view {};
|
||||||
} else {
|
} else {
|
||||||
name.size_ = sizeof(__PRETTY_FUNCTION__) - 36;
|
name.size_ = sizeof(__PRETTY_FUNCTION__) - 36;
|
||||||
|
@ -579,16 +558,13 @@ namespace magic_enum {
|
||||||
name.size_ -= 23;
|
name.size_ -= 23;
|
||||||
name.str_ += 23;
|
name.str_ += 23;
|
||||||
}
|
}
|
||||||
if (name.str_[0] == '(' || name.str_[0] == '-' ||
|
if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
|
||||||
(name.str_[0] >= '0' && name.str_[0] <= '9')) {
|
|
||||||
name = str_view {};
|
name = str_view {};
|
||||||
}
|
}
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
auto name = str_view { __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1 };
|
auto name = str_view { __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1 };
|
||||||
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
|
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
|
||||||
static_assert(
|
static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
|
||||||
always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__."
|
|
||||||
);
|
|
||||||
return str_view {};
|
return str_view {};
|
||||||
} else if (name.str_[name.size_ - 1] == ']') {
|
} else if (name.str_[name.size_ - 1] == ']') {
|
||||||
name.size_ -= 55;
|
name.size_ -= 55;
|
||||||
|
@ -640,8 +616,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
|
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
|
||||||
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
|
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
|
||||||
auto name =
|
auto name = name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
|
||||||
name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
|
|
||||||
#else
|
#else
|
||||||
// CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
|
// CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
|
||||||
str_view name;
|
str_view name;
|
||||||
|
@ -658,8 +633,7 @@ namespace magic_enum {
|
||||||
name.size_ -= p;
|
name.size_ -= p;
|
||||||
name.str_ += p;
|
name.str_ += p;
|
||||||
}
|
}
|
||||||
if (name.str_[0] == '(' || name.str_[0] == '-' ||
|
if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
|
||||||
(name.str_[0] >= '0' && name.str_[0] <= '9')) {
|
|
||||||
name = str_view {};
|
name = str_view {};
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
|
@ -775,32 +749,29 @@ namespace magic_enum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAGIC_ENUM_FOR_EACH_256(T) \
|
#define MAGIC_ENUM_FOR_EACH_256(T) \
|
||||||
T(0) \
|
T(0) \
|
||||||
T(1) T(2) T(3) T(4) T(5) T(6) T(7) T(8) T(9) T(10) T(11) T(12) T(13) T(14) T(15) T(16) T(17) \
|
T(1) \
|
||||||
T(18) T(19) T(20) T(21) T(22) T(23) T(24) T(25) T(26) T(27) T(28) T(29) T(30) T(31) T(32) \
|
T(2) T(3) T(4) T(5) T(6) T(7) T(8) T(9) T(10) T(11) T(12) T(13) T(14) T(15) T(16) T(17) T(18) T(19) T(20) \
|
||||||
T(33) T(34) T(35) T(36) T(37) T(38) T(39) T(40) T(41) T(42) T(43) T(44) T(45) T(46) T(47) \
|
T(21) T(22) T(23) T(24) T(25) T(26) T(27) T(28) T(29) T(30) T(31) T(32) T(33) T(34) T(35) T(36) T(37) \
|
||||||
T(48) T(49) T(50) T(51) T(52) T(53) T(54) T(55) T(56) T(57) T(58) T(59) T(60) T(61) T(62) \
|
T(38) T(39) T(40) T(41) T(42) T(43) T(44) T(45) T(46) T(47) T(48) T(49) T(50) T(51) T(52) T(53) T(54) \
|
||||||
T(63) T(64) T(65) T(66) T(67) T(68) T(69) T(70) T(71) T(72) T(73) T(74) T(75) T(76) \
|
T(55) T(56) T(57) T(58) T(59) T(60) T(61) T(62) T(63) T(64) T(65) T(66) T(67) T(68) T(69) T(70) \
|
||||||
T(77) T(78) T(79) T(80) T(81) T(82) T(83) T(84) T(85) T(86) T(87) T(88) T(89) T(90) \
|
T(71) T(72) T(73) T(74) T(75) T(76) T(77) T(78) T(79) T(80) T(81) T(82) T(83) T(84) T(85) T(86) \
|
||||||
T(91) T(92) T(93) T(94) T(95) T(96) T(97) T(98) T(99) T(100) T(101) T(102) T(103) \
|
T(87) T(88) T(89) T(90) T(91) T(92) T(93) T(94) T(95) T(96) T(97) T(98) T(99) T(100) T(101) \
|
||||||
T(104) T(105) T(106) T(107) T(108) T(109) T(110) T(111) T(112) T(113) T(114) \
|
T(102) T(103) T(104) T(105) T(106) T(107) T(108) T(109) T(110) T(111) T(112) T(113) T(114) \
|
||||||
T(115) T(116) T(117) T(118) T(119) T(120) T(121) T(122) T(123) T(124) T(125) \
|
T(115) T(116) T(117) T(118) T(119) T(120) T(121) T(122) T(123) T(124) T(125) T(126) T(127) \
|
||||||
T(126) T(127) T(128) T(129) T(130) T(131) T(132) T(133) T(134) T(135) T(136) \
|
T(128) T(129) T(130) T(131) T(132) T(133) T(134) T(135) T(136) T(137) T(138) T(139) T(140) \
|
||||||
T(137) T(138) T(139) T(140) T(141) T(142) T(143) T(144) T(145) T(146) T(147) \
|
T(141) T(142) T(143) T(144) T(145) T(146) T(147) T(148) T(149) T(150) T(151) T(152) \
|
||||||
T(148) T(149) T(150) T(151) T(152) T(153) T(154) T(155) T(156) T(157) \
|
T(153) T(154) T(155) T(156) T(157) T(158) T(159) T(160) T(161) T(162) T(163) T(164) \
|
||||||
T(158) T(159) T(160) T(161) T(162) T(163) T(164) T(165) T(166) T(167) \
|
T(165) T(166) T(167) T(168) T(169) T(170) T(171) T(172) T(173) T(174) T(175) T(176) \
|
||||||
T(168) T(169) T(170) T(171) T(172) T(173) T(174) T(175) T(176) T(177) \
|
T(177) T(178) T(179) T(180) T(181) T(182) T(183) T(184) T(185) T(186) T(187) \
|
||||||
T(178) T(179) T(180) T(181) T(182) T(183) T(184) T(185) T(186) \
|
T(188) T(189) T(190) T(191) T(192) T(193) T(194) T(195) T(196) T(197) T(198) \
|
||||||
T(187) T(188) T(189) T(190) T(191) T(192) T(193) T(194) T(195) \
|
T(199) T(200) T(201) T(202) T(203) T(204) T(205) T(206) T(207) T(208) T(209) \
|
||||||
T(196) T(197) T(198) T(199) T(200) T(201) T(202) T(203) T(204) \
|
T(210) T(211) T(212) T(213) T(214) T(215) T(216) T(217) T(218) T(219) T(220) \
|
||||||
T(205) T(206) T(207) T(208) T(209) T(210) T(211) T(212) T(213) \
|
T(221) T(222) T(223) T(224) T(225) T(226) T(227) T(228) T(229) T(230) \
|
||||||
T(214) T(215) T(216) T(217) T(218) T(219) T(220) T(221) \
|
T(231) T(232) T(233) T(234) T(235) T(236) T(237) T(238) T(239) T(240) \
|
||||||
T(222) T(223) T(224) T(225) T(226) T(227) T(228) T(229) \
|
T(241) T(242) T(243) T(244) T(245) T(246) T(247) T(248) T(249) T(250) \
|
||||||
T(230) T(231) T(232) T(233) T(234) T(235) T(236) T(237) \
|
T(251) T(252) T(253) T(254) T(255)
|
||||||
T(238) T(239) T(240) T(241) T(242) T(243) T(244) \
|
|
||||||
T(245) T(246) T(247) T(248) T(249) T(250) T(251) \
|
|
||||||
T(252) T(253) T(254) T(255)
|
|
||||||
|
|
||||||
template <typename E, enum_subtype S, std::size_t Size, int Min, std::size_t I>
|
template <typename E, enum_subtype S, std::size_t Size, int Min, std::size_t I>
|
||||||
constexpr void valid_count(bool* valid, std::size_t& count) noexcept {
|
constexpr void valid_count(bool* valid, std::size_t& count) noexcept {
|
||||||
|
@ -913,12 +884,10 @@ namespace magic_enum {
|
||||||
inline constexpr auto count_v = values_v<E, S>.size();
|
inline constexpr auto count_v = values_v<E, S>.size();
|
||||||
|
|
||||||
template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
|
template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
|
||||||
inline constexpr auto min_v =
|
inline constexpr auto min_v = (count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.front()) : U { 0 };
|
||||||
(count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.front()) : U { 0 };
|
|
||||||
|
|
||||||
template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
|
template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
|
||||||
inline constexpr auto max_v =
|
inline constexpr auto max_v = (count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.back()) : U { 0 };
|
||||||
(count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.back()) : U { 0 };
|
|
||||||
|
|
||||||
template <typename E, enum_subtype S, std::size_t... I>
|
template <typename E, enum_subtype S, std::size_t... I>
|
||||||
constexpr auto names(std::index_sequence<I...>) noexcept {
|
constexpr auto names(std::index_sequence<I...>) noexcept {
|
||||||
|
@ -1094,9 +1063,8 @@ namespace magic_enum {
|
||||||
constexpr std::uint32_t operator()(string_view value) const noexcept {
|
constexpr std::uint32_t operator()(string_view value) const noexcept {
|
||||||
auto acc = static_cast<std::uint64_t>(2166136261ULL);
|
auto acc = static_cast<std::uint64_t>(2166136261ULL);
|
||||||
for (const auto c : value) {
|
for (const auto c : value) {
|
||||||
acc =
|
acc = ((acc ^ static_cast<std::uint64_t>(c)) * static_cast<std::uint64_t>(16777619ULL)) &
|
||||||
((acc ^ static_cast<std::uint64_t>(c)) * static_cast<std::uint64_t>(16777619ULL)) &
|
(std::numeric_limits<std::uint32_t>::max)();
|
||||||
(std::numeric_limits<std::uint32_t>::max)();
|
|
||||||
}
|
}
|
||||||
return static_cast<std::uint32_t>(acc);
|
return static_cast<std::uint32_t>(acc);
|
||||||
}
|
}
|
||||||
|
@ -1140,8 +1108,7 @@ namespace magic_enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename R, typename F, typename... Args>
|
template <typename R, typename F, typename... Args>
|
||||||
constexpr R
|
constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
|
||||||
invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
|
|
||||||
if constexpr (std::is_void_v<R>) {
|
if constexpr (std::is_void_v<R>) {
|
||||||
std::forward<F>(f)(std::forward<Args>(args)...);
|
std::forward<F>(f)(std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1181,47 +1148,41 @@ namespace magic_enum {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAGIC_ENUM_CASE(val) \
|
#define MAGIC_ENUM_CASE(val) \
|
||||||
case cases[val]: \
|
case cases[val]: \
|
||||||
if constexpr ((val) + Page < size) { \
|
if constexpr ((val) + Page < size) { \
|
||||||
if (!pred(values[val + Page], searched)) { \
|
if (!pred(values[val + Page], searched)) { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
if constexpr (CallValue == case_call_t::index) { \
|
if constexpr (CallValue == case_call_t::index) { \
|
||||||
if constexpr (std::is_invocable_r_v< \
|
if constexpr (std::is_invocable_r_v< \
|
||||||
result_t, \
|
result_t, \
|
||||||
Lambda, \
|
Lambda, \
|
||||||
std::integral_constant<std::size_t, val + Page>>) { \
|
std::integral_constant<std::size_t, val + Page>>) { \
|
||||||
return detail::invoke_r<result_t>( \
|
return detail::invoke_r<result_t>( \
|
||||||
std::forward<Lambda>(lambda), std::integral_constant<std::size_t, val + Page> {} \
|
std::forward<Lambda>(lambda), std::integral_constant<std::size_t, val + Page> {} \
|
||||||
); \
|
); \
|
||||||
} else if constexpr (std::is_invocable_v< \
|
} else if constexpr (std::is_invocable_v<Lambda, std::integral_constant<std::size_t, val + Page>>) { \
|
||||||
Lambda, \
|
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
|
||||||
std::integral_constant<std::size_t, val + Page>>) { \
|
} \
|
||||||
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
|
} else if constexpr (CallValue == case_call_t::value) { \
|
||||||
} \
|
if constexpr (std::is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
|
||||||
} else if constexpr (CallValue == case_call_t::value) { \
|
return detail::invoke_r<result_t>( \
|
||||||
if constexpr (std:: \
|
std::forward<Lambda>(lambda), enum_constant<values[val + Page]> {} \
|
||||||
is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
|
); \
|
||||||
return detail::invoke_r<result_t>( \
|
} else if constexpr (std::is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
|
||||||
std::forward<Lambda>(lambda), enum_constant<values[val + Page]> {} \
|
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
|
||||||
); \
|
} \
|
||||||
} else if constexpr (std::is_invocable_r_v< \
|
} \
|
||||||
result_t, \
|
break; \
|
||||||
Lambda, \
|
} else \
|
||||||
enum_constant<values[val + Page]>>) { \
|
|
||||||
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} else \
|
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
template <
|
template <
|
||||||
auto* GlobValues,
|
auto* GlobValues,
|
||||||
case_call_t CallValue,
|
case_call_t CallValue,
|
||||||
std::size_t Page = 0,
|
std::size_t Page = 0,
|
||||||
typename Hash = constexpr_hash_t<typename std::decay_t<decltype(*GlobValues)>::value_type>,
|
typename Hash = constexpr_hash_t<typename std::decay_t<decltype(*GlobValues)>::value_type>,
|
||||||
typename BinaryPredicate = std::equal_to<>,
|
typename BinaryPredicate = std::equal_to<>,
|
||||||
typename Lambda,
|
typename Lambda,
|
||||||
typename ResultGetterType>
|
typename ResultGetterType>
|
||||||
|
@ -1328,8 +1289,8 @@ namespace magic_enum {
|
||||||
if constexpr (detail::is_sparse_v<D, S>) {
|
if constexpr (detail::is_sparse_v<D, S>) {
|
||||||
return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::values_v<D, S>[index];
|
return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::values_v<D, S>[index];
|
||||||
} else {
|
} else {
|
||||||
constexpr auto min = (S == detail::enum_subtype::flags) ? detail::log2(detail::min_v<D, S>)
|
constexpr auto min =
|
||||||
: detail::min_v<D, S>;
|
(S == detail::enum_subtype::flags) ? detail::log2(detail::min_v<D, S>) : detail::min_v<D, S>;
|
||||||
|
|
||||||
return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::value<D, min, S>(index);
|
return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::value<D, min, S>(index);
|
||||||
}
|
}
|
||||||
|
@ -1349,8 +1310,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
// Returns std::array with enum values, sorted by enum value.
|
// Returns std::array with enum values, sorted by enum value.
|
||||||
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
||||||
[[nodiscard]] constexpr auto enum_values() noexcept
|
[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t<E, detail::values_t<E, S>> {
|
||||||
-> detail::enable_if_t<E, detail::values_t<E, S>> {
|
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
||||||
|
@ -1376,8 +1336,7 @@ namespace magic_enum {
|
||||||
// Obtains index in enum values from enum value.
|
// Obtains index in enum values from enum value.
|
||||||
// Returns optional with index.
|
// Returns optional with index.
|
||||||
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
||||||
[[nodiscard]] constexpr auto enum_index(E value
|
[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
|
||||||
) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
|
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
using U = underlying_type_t<D>;
|
using U = underlying_type_t<D>;
|
||||||
static_assert(
|
static_assert(
|
||||||
|
@ -1410,8 +1369,7 @@ namespace magic_enum {
|
||||||
// Obtains index in enum values from enum value.
|
// Obtains index in enum values from enum value.
|
||||||
// Returns optional with index.
|
// Returns optional with index.
|
||||||
template <detail::enum_subtype S, typename E>
|
template <detail::enum_subtype S, typename E>
|
||||||
[[nodiscard]] constexpr auto enum_index(E value
|
[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
|
||||||
) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
|
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
||||||
|
@ -1422,8 +1380,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
// Obtains index in enum values from static storage enum variable.
|
// Obtains index in enum values from static storage enum variable.
|
||||||
template <auto V, detail::enum_subtype S = detail::subtype_v<std::decay_t<decltype(V)>>>
|
template <auto V, detail::enum_subtype S = detail::subtype_v<std::decay_t<decltype(V)>>>
|
||||||
[[nodiscard]] constexpr auto enum_index() noexcept
|
[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t<decltype(V), std::size_t> {
|
||||||
-> detail::enable_if_t<decltype(V), std::size_t> {
|
|
||||||
using D = std::decay_t<decltype(V)>;
|
using D = std::decay_t<decltype(V)>;
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
||||||
|
@ -1438,8 +1395,7 @@ namespace magic_enum {
|
||||||
// This version is much lighter on the compile times and is not restricted to the enum_range
|
// This version is much lighter on the compile times and is not restricted to the enum_range
|
||||||
// limitation.
|
// limitation.
|
||||||
template <auto V>
|
template <auto V>
|
||||||
[[nodiscard]] constexpr auto enum_name() noexcept
|
[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t<decltype(V), string_view> {
|
||||||
-> detail::enable_if_t<decltype(V), string_view> {
|
|
||||||
constexpr string_view name = detail::enum_name_v<std::decay_t<decltype(V)>, V>;
|
constexpr string_view name = detail::enum_name_v<std::decay_t<decltype(V)>, V>;
|
||||||
static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name.");
|
static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name.");
|
||||||
|
|
||||||
|
@ -1475,8 +1431,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
// Returns std::array with names, sorted by enum value.
|
// Returns std::array with names, sorted by enum value.
|
||||||
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
||||||
[[nodiscard]] constexpr auto enum_names() noexcept
|
[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t<E, detail::names_t<E, S>> {
|
||||||
-> detail::enable_if_t<E, detail::names_t<E, S>> {
|
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
||||||
|
@ -1487,8 +1442,7 @@ namespace magic_enum {
|
||||||
|
|
||||||
// Returns std::array with pairs (value, name), sorted by enum value.
|
// Returns std::array with pairs (value, name), sorted by enum value.
|
||||||
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
|
||||||
[[nodiscard]] constexpr auto enum_entries() noexcept
|
[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t<E, detail::entries_t<E, S>> {
|
||||||
-> detail::enable_if_t<E, detail::entries_t<E, S>> {
|
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."
|
||||||
|
@ -1538,10 +1492,8 @@ namespace magic_enum {
|
||||||
typename E,
|
typename E,
|
||||||
detail::enum_subtype S = detail::subtype_v<E>,
|
detail::enum_subtype S = detail::subtype_v<E>,
|
||||||
typename BinaryPredicate = std::equal_to<>>
|
typename BinaryPredicate = std::equal_to<>>
|
||||||
[[nodiscard]] constexpr auto enum_cast(
|
[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(
|
||||||
string_view value,
|
detail::is_nothrow_invocable<BinaryPredicate>()
|
||||||
[[maybe_unused]] BinaryPredicate p = {}
|
|
||||||
) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()
|
|
||||||
) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
|
) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(
|
static_assert(
|
||||||
|
@ -1638,12 +1590,10 @@ namespace magic_enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool AsFlags = true>
|
template <bool AsFlags = true>
|
||||||
inline constexpr auto as_flags =
|
inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common;
|
||||||
AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common;
|
|
||||||
|
|
||||||
template <bool AsFlags = true>
|
template <bool AsFlags = true>
|
||||||
inline constexpr auto as_common =
|
inline constexpr auto as_common = AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags;
|
||||||
AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags;
|
|
||||||
|
|
||||||
namespace bitwise_operators {
|
namespace bitwise_operators {
|
||||||
|
|
||||||
|
@ -1654,23 +1604,17 @@ namespace magic_enum {
|
||||||
|
|
||||||
template <typename E, detail::enable_if_t<E, int> = 0>
|
template <typename E, detail::enable_if_t<E, int> = 0>
|
||||||
constexpr E operator|(E lhs, E rhs) noexcept {
|
constexpr E operator|(E lhs, E rhs) noexcept {
|
||||||
return static_cast<E>(
|
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) | static_cast<underlying_type_t<E>>(rhs));
|
||||||
static_cast<underlying_type_t<E>>(lhs) | static_cast<underlying_type_t<E>>(rhs)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, detail::enable_if_t<E, int> = 0>
|
template <typename E, detail::enable_if_t<E, int> = 0>
|
||||||
constexpr E operator&(E lhs, E rhs) noexcept {
|
constexpr E operator&(E lhs, E rhs) noexcept {
|
||||||
return static_cast<E>(
|
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) & static_cast<underlying_type_t<E>>(rhs));
|
||||||
static_cast<underlying_type_t<E>>(lhs) & static_cast<underlying_type_t<E>>(rhs)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, detail::enable_if_t<E, int> = 0>
|
template <typename E, detail::enable_if_t<E, int> = 0>
|
||||||
constexpr E operator^(E lhs, E rhs) noexcept {
|
constexpr E operator^(E lhs, E rhs) noexcept {
|
||||||
return static_cast<E>(
|
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) ^ static_cast<underlying_type_t<E>>(rhs));
|
||||||
static_cast<underlying_type_t<E>>(lhs) ^ static_cast<underlying_type_t<E>>(rhs)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, detail::enable_if_t<E, int> = 0>
|
template <typename E, detail::enable_if_t<E, int> = 0>
|
||||||
|
|
Loading…
Reference in a new issue