started transition to vulkan-hpp

This commit is contained in:
Mars 2024-09-29 20:12:56 -04:00
parent bda0032e44
commit 12c4d95aff
Signed by: pupbrained
GPG key ID: 0FF5B8826803F895
3 changed files with 124 additions and 182 deletions

View file

@ -41,7 +41,6 @@
vulkan-extension-layer
vulkan-memory-allocator
vulkan-utility-libraries
vulkan-headers
vulkan-loader
vulkan-tools
];

View file

@ -1,3 +1,6 @@
#define VULKAN_HPP_NO_CONSTRUCTORS
#include <vulkan/vulkan.hpp>
#define GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
@ -11,7 +14,6 @@
#include <set>
#include <span>
#include <stdexcept>
#include <vulkan/vulkan_core.h>
#include "util/magic_enum.hpp"
#include "util/types.h"
@ -144,44 +146,41 @@ class Application {
if (enableValidationLayers && !checkValidationLayerSupport())
throw std::runtime_error("validation layers requested, but not available!");
VkApplicationInfo appInfo {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
vk::ApplicationInfo appInfo { .pApplicationName = "Hello Triangle",
.applicationVersion = 1,
.pEngineName = "No Engine",
.engineVersion = 1,
.apiVersion = VK_API_VERSION_1_1 };
VkInstanceCreateInfo createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
vk::InstanceCreateInfo createInfo { .pApplicationInfo = &appInfo };
// Retrieve extensions using custom function
std::vector<const char*> extensions = getRequiredExtensions();
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<u32>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
createInfo.setEnabledLayerCount(static_cast<uint32_t>(validationLayers.size()))
.setPpEnabledLayerNames(validationLayers.data());
populateDebugMessengerCreateInfo(debugCreateInfo);
createInfo.pNext = static_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
createInfo.setPNext(&debugCreateInfo);
} else {
createInfo.enabledLayerCount = 0;
createInfo.pNext = nullptr;
createInfo.setEnabledLayerCount(0).setPNext(nullptr);
}
extensions.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
createInfo.enabledExtensionCount = static_cast<u32>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
// Enable the portability extension and set flags
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
createInfo.setEnabledExtensionCount(static_cast<uint32_t>(extensions.size()))
.setPpEnabledExtensionNames(extensions.data())
.setFlags(vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR);
for (const char* extension : extensions) std::cout << extension << std::endl;
if (vkCreateInstance(&createInfo, nullptr, &mInstance) != VK_SUCCESS)
throw std::runtime_error("failed to create instance!");
try {
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 {

View file

@ -78,16 +78,15 @@
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'.
#pragma GCC diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for
// char_type = char (common on Linux).
#pragma GCC diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for
// char_type = char (common on Linux).
#elif defined(_MSC_VER)
#pragma warning(push)
#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
// then casting the result to a 8 byte value.
#pragma warning(disable : 26451 \
) // 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 : 26451) // 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.
#endif
// Checks magic_enum compiler compatibility.
@ -163,10 +162,8 @@ namespace magic_enum {
static_assert(
[] {
if constexpr (std::is_same_v<char_type, wchar_t>) {
constexpr const char c[] =
"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
constexpr const wchar_t wc[] =
L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
constexpr const char c[] = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
constexpr const wchar_t wc[] = L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
static_assert(
std::size(c) == std::size(wc),
"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> {
public:
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(detail::customize_tag tag)
: std::pair<detail::customize_tag, string_view> { tag, string_view {} } {
@ -249,10 +245,7 @@ namespace magic_enum {
};
#endif
template <
auto V,
typename E = std::decay_t<decltype(V)>,
std::enable_if_t<std::is_enum_v<E>, int> = 0>
template <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>;
template <typename... T>
@ -263,26 +256,22 @@ namespace magic_enum {
template <typename T>
struct has_is_flags<T, std::void_t<decltype(customize::enum_range<T>::is_flags)>>
: std::bool_constant<
std::is_same_v<bool, std::decay_t<decltype(customize::enum_range<T>::is_flags)>>> {};
: std::bool_constant<std::is_same_v<bool, std::decay_t<decltype(customize::enum_range<T>::is_flags)>>> {
};
template <typename T, typename = void>
struct range_min : std::integral_constant<int, MAGIC_ENUM_RANGE_MIN> {};
template <typename T>
struct range_min<T, std::void_t<decltype(customize::enum_range<T>::min)>>
: std::integral_constant<
decltype(customize::enum_range<T>::min),
customize::enum_range<T>::min> {};
: std::integral_constant<decltype(customize::enum_range<T>::min), customize::enum_range<T>::min> {};
template <typename T, typename = void>
struct range_max : std::integral_constant<int, MAGIC_ENUM_RANGE_MAX> {};
template <typename T>
struct range_max<T, std::void_t<decltype(customize::enum_range<T>::max)>>
: std::integral_constant<
decltype(customize::enum_range<T>::max),
customize::enum_range<T>::max> {};
: std::integral_constant<decltype(customize::enum_range<T>::max), customize::enum_range<T>::max> {};
struct str_view {
const char* str_ = nullptr;
@ -340,9 +329,7 @@ namespace magic_enum {
class case_insensitive {
static constexpr char_type to_lower(char_type c) noexcept {
return (c >= static_cast<char_type>('A') && c <= static_cast<char_type>('Z'))
? static_cast<char_type>(
c + (static_cast<char_type>('a') - static_cast<char_type>('A'))
)
? static_cast<char_type>(c + (static_cast<char_type>('a') - static_cast<char_type>('A')))
: c;
}
@ -381,8 +368,7 @@ namespace magic_enum {
template <typename BinaryPredicate>
constexpr bool is_default_predicate() noexcept {
return std::
is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<string_view::value_type>> ||
return std::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<>>;
}
@ -393,11 +379,9 @@ namespace magic_enum {
}
template <typename BinaryPredicate>
constexpr bool cmp_equal(
string_view lhs,
string_view rhs,
[[maybe_unused]] BinaryPredicate&& p
) noexcept(is_nothrow_invocable<BinaryPredicate>()) {
constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(
is_nothrow_invocable<BinaryPredicate>()
) {
#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/232218/c-constexpr-string-view.html
@ -427,8 +411,7 @@ namespace magic_enum {
template <typename L, typename R>
constexpr bool cmp_less(L lhs, R rhs) noexcept {
static_assert(
std::is_integral_v<L> && std::is_integral_v<R>,
"magic_enum::detail::cmp_less requires integral type."
std::is_integral_v<L> && std::is_integral_v<R>, "magic_enum::detail::cmp_less requires integral type."
);
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
#else
template <typename T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
to_array(T (&a)[N], std::index_sequence<I...>) noexcept {
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N], std::index_sequence<I...>) noexcept {
return { { a[I]... } };
}
#endif
@ -561,14 +543,11 @@ namespace magic_enum {
if constexpr (supported<decltype(V)>::value) {
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
auto name =
name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
auto name = name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
#elif defined(__clang__)
str_view name;
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
static_assert(
always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__."
);
static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
return str_view {};
} else {
name.size_ = sizeof(__PRETTY_FUNCTION__) - 36;
@ -579,16 +558,13 @@ namespace magic_enum {
name.size_ -= 23;
name.str_ += 23;
}
if (name.str_[0] == '(' || name.str_[0] == '-' ||
(name.str_[0] >= '0' && name.str_[0] <= '9')) {
if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
name = str_view {};
}
#elif defined(__GNUC__)
auto name = str_view { __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1 };
if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
static_assert(
always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__."
);
static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
return str_view {};
} else if (name.str_[name.size_ - 1] == ']') {
name.size_ -= 55;
@ -640,8 +616,7 @@ namespace magic_enum {
#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
auto name =
name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
auto name = name_ptr ? str_view { name_ptr, std::char_traits<char>::length(name_ptr) } : str_view {};
#else
// CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
str_view name;
@ -658,8 +633,7 @@ namespace magic_enum {
name.size_ -= p;
name.str_ += p;
}
if (name.str_[0] == '(' || name.str_[0] == '-' ||
(name.str_[0] >= '0' && name.str_[0] <= '9')) {
if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
name = str_view {};
}
return name;
@ -775,32 +749,29 @@ namespace magic_enum {
}
}
#define MAGIC_ENUM_FOR_EACH_256(T) \
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(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(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(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(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(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(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(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(126) T(127) 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(141) T(142) T(143) T(144) T(145) T(146) T(147) \
T(148) T(149) T(150) T(151) T(152) 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(165) T(166) T(167) \
T(168) T(169) T(170) T(171) T(172) T(173) T(174) T(175) T(176) T(177) \
T(178) T(179) T(180) T(181) T(182) T(183) T(184) T(185) T(186) \
T(187) T(188) T(189) T(190) T(191) T(192) T(193) T(194) T(195) \
T(196) T(197) T(198) T(199) T(200) T(201) T(202) T(203) T(204) \
T(205) T(206) T(207) T(208) T(209) T(210) T(211) T(212) T(213) \
T(214) T(215) T(216) T(217) T(218) T(219) T(220) T(221) \
T(222) T(223) T(224) T(225) T(226) T(227) T(228) T(229) \
T(230) T(231) T(232) T(233) T(234) T(235) T(236) T(237) \
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)
#define MAGIC_ENUM_FOR_EACH_256(T) \
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(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(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(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(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(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(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(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(126) T(127) \
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(141) T(142) T(143) T(144) T(145) T(146) T(147) T(148) T(149) T(150) T(151) T(152) \
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(165) T(166) T(167) T(168) T(169) T(170) T(171) T(172) T(173) T(174) T(175) T(176) \
T(177) T(178) T(179) T(180) T(181) T(182) T(183) T(184) T(185) T(186) T(187) \
T(188) T(189) T(190) T(191) T(192) T(193) T(194) T(195) T(196) T(197) T(198) \
T(199) T(200) T(201) T(202) T(203) T(204) T(205) T(206) T(207) T(208) T(209) \
T(210) T(211) T(212) T(213) T(214) T(215) T(216) T(217) T(218) T(219) T(220) \
T(221) T(222) T(223) T(224) T(225) T(226) T(227) T(228) T(229) T(230) \
T(231) T(232) T(233) T(234) T(235) T(236) T(237) 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>
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();
template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
inline constexpr auto min_v =
(count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.front()) : U { 0 };
inline constexpr auto min_v = (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>>
inline constexpr auto max_v =
(count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.back()) : U { 0 };
inline constexpr auto max_v = (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>
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 {
auto acc = static_cast<std::uint64_t>(2166136261ULL);
for (const auto c : value) {
acc =
((acc ^ static_cast<std::uint64_t>(c)) * static_cast<std::uint64_t>(16777619ULL)) &
(std::numeric_limits<std::uint32_t>::max)();
acc = ((acc ^ static_cast<std::uint64_t>(c)) * static_cast<std::uint64_t>(16777619ULL)) &
(std::numeric_limits<std::uint32_t>::max)();
}
return static_cast<std::uint32_t>(acc);
}
@ -1140,8 +1108,7 @@ namespace magic_enum {
}
template <typename R, typename F, typename... Args>
constexpr R
invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
if constexpr (std::is_void_v<R>) {
std::forward<F>(f)(std::forward<Args>(args)...);
} else {
@ -1181,47 +1148,41 @@ namespace magic_enum {
return true;
}
#define MAGIC_ENUM_CASE(val) \
case cases[val]: \
if constexpr ((val) + Page < size) { \
if (!pred(values[val + Page], searched)) { \
break; \
} \
if constexpr (CallValue == case_call_t::index) { \
if constexpr (std::is_invocable_r_v< \
result_t, \
Lambda, \
std::integral_constant<std::size_t, val + Page>>) { \
return detail::invoke_r<result_t>( \
std::forward<Lambda>(lambda), std::integral_constant<std::size_t, val + Page> {} \
); \
} else if constexpr (std::is_invocable_v< \
Lambda, \
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]>>) { \
return detail::invoke_r<result_t>( \
std::forward<Lambda>(lambda), enum_constant<values[val + Page]> {} \
); \
} else if constexpr (std::is_invocable_r_v< \
result_t, \
Lambda, \
enum_constant<values[val + Page]>>) { \
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
} \
} \
break; \
} else \
#define MAGIC_ENUM_CASE(val) \
case cases[val]: \
if constexpr ((val) + Page < size) { \
if (!pred(values[val + Page], searched)) { \
break; \
} \
if constexpr (CallValue == case_call_t::index) { \
if constexpr (std::is_invocable_r_v< \
result_t, \
Lambda, \
std::integral_constant<std::size_t, val + Page>>) { \
return detail::invoke_r<result_t>( \
std::forward<Lambda>(lambda), std::integral_constant<std::size_t, val + Page> {} \
); \
} else if constexpr (std::is_invocable_v<Lambda, 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]>>) { \
return detail::invoke_r<result_t>( \
std::forward<Lambda>(lambda), enum_constant<values[val + Page]> {} \
); \
} else if constexpr (std::is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
} \
} \
break; \
} else \
[[fallthrough]];
template <
auto* GlobValues,
case_call_t CallValue,
std::size_t Page = 0,
typename Hash = constexpr_hash_t<typename std::decay_t<decltype(*GlobValues)>::value_type>,
std::size_t Page = 0,
typename Hash = constexpr_hash_t<typename std::decay_t<decltype(*GlobValues)>::value_type>,
typename BinaryPredicate = std::equal_to<>,
typename Lambda,
typename ResultGetterType>
@ -1328,8 +1289,8 @@ namespace magic_enum {
if constexpr (detail::is_sparse_v<D, S>) {
return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::values_v<D, S>[index];
} else {
constexpr auto min = (S == detail::enum_subtype::flags) ? detail::log2(detail::min_v<D, S>)
: detail::min_v<D, S>;
constexpr auto min =
(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);
}
@ -1349,8 +1310,7 @@ namespace magic_enum {
// Returns std::array with enum values, sorted by enum value.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_values() noexcept
-> detail::enable_if_t<E, detail::values_t<E, S>> {
[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t<E, detail::values_t<E, S>> {
using D = std::decay_t<E>;
static_assert(
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.
// Returns optional with index.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_index(E value
) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
using D = std::decay_t<E>;
using U = underlying_type_t<D>;
static_assert(
@ -1410,8 +1369,7 @@ namespace magic_enum {
// Obtains index in enum values from enum value.
// Returns optional with index.
template <detail::enum_subtype S, typename E>
[[nodiscard]] constexpr auto enum_index(E value
) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
using D = std::decay_t<E>;
static_assert(
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.
template <auto V, detail::enum_subtype S = detail::subtype_v<std::decay_t<decltype(V)>>>
[[nodiscard]] constexpr auto enum_index() noexcept
-> detail::enable_if_t<decltype(V), std::size_t> {
[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t<decltype(V), std::size_t> {
using D = std::decay_t<decltype(V)>;
static_assert(
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
// limitation.
template <auto V>
[[nodiscard]] constexpr auto enum_name() noexcept
-> detail::enable_if_t<decltype(V), string_view> {
[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t<decltype(V), string_view> {
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.");
@ -1475,8 +1431,7 @@ namespace magic_enum {
// Returns std::array with names, sorted by enum value.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_names() noexcept
-> detail::enable_if_t<E, detail::names_t<E, S>> {
[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t<E, detail::names_t<E, S>> {
using D = std::decay_t<E>;
static_assert(
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.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_entries() noexcept
-> detail::enable_if_t<E, detail::entries_t<E, S>> {
[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t<E, detail::entries_t<E, S>> {
using D = std::decay_t<E>;
static_assert(
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,
detail::enum_subtype S = detail::subtype_v<E>,
typename BinaryPredicate = std::equal_to<>>
[[nodiscard]] constexpr auto enum_cast(
string_view value,
[[maybe_unused]] BinaryPredicate p = {}
) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()
[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(
detail::is_nothrow_invocable<BinaryPredicate>()
) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
using D = std::decay_t<E>;
static_assert(
@ -1638,12 +1590,10 @@ namespace magic_enum {
}
template <bool AsFlags = true>
inline constexpr auto as_flags =
AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common;
inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common;
template <bool AsFlags = true>
inline constexpr auto as_common =
AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags;
inline constexpr auto as_common = AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags;
namespace bitwise_operators {
@ -1654,23 +1604,17 @@ namespace magic_enum {
template <typename E, detail::enable_if_t<E, int> = 0>
constexpr E operator|(E lhs, E rhs) noexcept {
return static_cast<E>(
static_cast<underlying_type_t<E>>(lhs) | static_cast<underlying_type_t<E>>(rhs)
);
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) | static_cast<underlying_type_t<E>>(rhs));
}
template <typename E, detail::enable_if_t<E, int> = 0>
constexpr E operator&(E lhs, E rhs) noexcept {
return static_cast<E>(
static_cast<underlying_type_t<E>>(lhs) & static_cast<underlying_type_t<E>>(rhs)
);
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) & static_cast<underlying_type_t<E>>(rhs));
}
template <typename E, detail::enable_if_t<E, int> = 0>
constexpr E operator^(E lhs, E rhs) noexcept {
return static_cast<E>(
static_cast<underlying_type_t<E>>(lhs) ^ static_cast<underlying_type_t<E>>(rhs)
);
return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) ^ static_cast<underlying_type_t<E>>(rhs));
}
template <typename E, detail::enable_if_t<E, int> = 0>