45 #ifndef SUMTY_UTILS_HPP
46 #define SUMTY_UTILS_HPP
50 #include <type_traits>
53 #if defined(__GNUC__) && !defined(__clang__)
54 #pragma GCC diagnostic push
55 #pragma GCC diagnostic ignored "-Wterminate"
60 #pragma warning(disable : 4297
)
61 #pragma warning(disable : 4645
)
62 #pragma warning(disable : 4702
)
65 #if defined(_MSC_VER) && !defined(__clang__)
66 #define SUMTY_NO_UNIQ_ADDR [[msvc::no_unique_address]]
68 #define SUMTY_NO_UNIQ_ADDR [[no_unique_address]]
73 using std::in_place_index_t;
74 using std::in_place_t;
75 using std::in_place_type_t;
76 using in_place_error_t = in_place_index_t<1>;
79 using std::in_place_index;
80 using std::in_place_type;
81 static inline constexpr in_place_error_t in_place_error = in_place_index<1>;
93 operator()(S&& s)
const
95 requires requires { std::forward<S>(s)[index_t<N>{}]; }
98 return std::forward<S>(s)[
index_t<N>{}];
104 static inline constexpr index_t<N> index{};
108 static inline constexpr index_t<N> index_v{};
111 template <
typename T>
113 template <
typename S>
120 operator()(S&& s)
const
122 requires requires { std::forward<S>(s)[type_t<T>{}]; }
125 return std::forward<S>(s)[
type_t<T>{}];
130 template <
typename T>
131 static inline constexpr type_t<T> type{};
134 template <
typename T>
135 static inline constexpr type_t<T> type_v{};
139 constexpr void_t()
noexcept =
default;
141 constexpr void_t(
const void_t&)
noexcept =
default;
143 constexpr void_t(
void_t&&)
noexcept =
default;
145 constexpr ~void_t()
noexcept =
default;
147 constexpr void_t& operator=(
const void_t&)
noexcept =
default;
149 constexpr void_t& operator=(
void_t&&)
noexcept =
default;
151 template <
typename T>
152 requires(std::is_default_constructible_v<T>)
153 explicit constexpr operator T()
const
154 noexcept(std::is_nothrow_default_constructible_v<T>) {
160 static inline constexpr void_t void_v{};
166 static inline constexpr none_t none{};
169 static inline constexpr none_t none_v{};
202 [[
noreturn]]
static constexpr void unreachable()
noexcept {
203 if (std::is_constant_evaluated()) {
210 #ifdef __cpp_lib_unreachable
212 #elif defined(_MSC_VER) && !defined(__clang__)
214 #elif defined(__GNUC__)
215 __builtin_unreachable();
234 [[
noreturn]]
constexpr never([[maybe_unused]]
const never& other)
noexcept {
238 [[
noreturn]]
constexpr never([[maybe_unused]]
never&& other)
noexcept { unreachable(); }
240 [[
noreturn]]
constexpr ~never()
noexcept { unreachable(); }
243 constexpr never& operator=([[maybe_unused]]
const never& rhs)
noexcept {
248 constexpr never& operator=([[maybe_unused]]
never&& rhs)
noexcept {
257 template <
typename T>
259 [[noreturn]]
constexpr operator T()
const noexcept {
266 template <
typename... T>
268 using T::operator()...;
271 template <
typename... T>
298 template <
typename F,
typename... Args>
301 std::conditional_t<std::is_void_v<std::invoke_result_t<F, Args...>>,
303 std::invoke_result_t<F, Args...>>
307 invoke(F&& f, Args&&... args) {
308 using ret_t = std::invoke_result_t<F, Args...>;
309 if constexpr (std::is_void_v<ret_t>) {
310 std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
313 return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
319 #if defined(__GNUC__) && !defined(__clang__)
320 #pragma GCC diagnostic pop
323 #if defined(_MSC_VER)