1#ifndef NNGN_UTILS_UTILS_H
2#define NNGN_UTILS_UTILS_H
16#include "concepts/fundamental.h"
18#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
20#define NNGN_DEFAULT_CONSTRUCT(x) \
22 x(const x&) = default; \
23 x &operator=(const x&) = default; \
24 x(x&&) noexcept = default; \
25 x &operator=(x&&) noexcept = default; \
27#define NNGN_VIRTUAL(x) \
28 NNGN_DEFAULT_CONSTRUCT(x) \
29 virtual ~x() = default;
31#define NNGN_PURE_VIRTUAL(x) \
32 NNGN_DEFAULT_CONSTRUCT(x) \
35#define NNGN_NO_COPY(x) \
36 x(const x&) = delete; \
37 x &operator=(const x&) = delete;
39#define NNGN_MOVE_ONLY(x) \
41 x(x&&) noexcept = default; \
42 x &operator=(x&&) noexcept = default;
44#define NNGN_NO_MOVE(x) \
45 x(const x&) = delete; \
46 x &operator=(const x&) = delete; \
47 x(x&&) noexcept = delete; \
48 x &operator=(x&&) noexcept = delete;
50#define NNGN_ANON_IMPL1(l) nngn_anon_ ## l
51#define NNGN_ANON_IMPL0(l) NNGN_ANON_IMPL1(l)
52#define NNGN_ANON() NNGN_ANON_IMPL0(__LINE__)
53#define NNGN_ANON_DECL(...) \
54 [[maybe_unused]] const auto NNGN_ANON() = __VA_ARGS__;
56#define NNGN_CONTAINER_OF(t, n, p) \
57 (nngn::byte_cast<t*>(nngn::byte_cast<char*>(p) - offsetof(t, n)))
59#define NNGN_BIND_MEM_FN(x, f) \
60 std::bind_front([] { \
61 constexpr auto nngn_ret = \
62 &std::remove_pointer_t<std::decay_t<decltype(x)>>::f; \
63 static_assert(std::is_member_function_pointer_v<decltype(nngn_ret)>); \
67#define NNGN_EXPOSE_ITERATOR(n, m) \
68 NNGN_EXPOSE_ITERATOR0(n, m, cbegin) \
69 NNGN_EXPOSE_ITERATOR0(n, m, cend) \
70 NNGN_EXPOSE_ITERATOR0(n, m, begin) \
71 NNGN_EXPOSE_ITERATOR0(n, m, end)
72#define NNGN_EXPOSE_ITERATOR0(n, m, i) \
73 auto n##i(void) const { using std::i; return i(this->m); } \
74 auto n##i(void) { using std::i; return i(this->m); }
82 constexpr decltype(
auto)
operator<<(
auto &&x) {
83 return static_cast<T>(
FWD(x));
91template<
typename T>
struct always_false : std::false_type {};
94template<
typename ...Ts>
96 return (detail::chain_cast<Ts>{} << ... <<
FWD(x));
100template<
typename To,
typename From>
102 To ret =
static_cast<To
>(x);
103 assert(
static_cast<From
>(ret) == x);
108template<
typename T,
typename U>
109constexpr decltype(
auto)
cast(U &&x) {
110 if constexpr(
requires {
const_cast<T>(
FWD(x)); })
111 return const_cast<T>(
FWD(x));
112 else if constexpr(
requires {
static_cast<T>(
FWD(x)); })
113 return static_cast<T>(
FWD(x));
115 return reinterpret_cast<T>(
FWD(x));
119template<
typename To,
typename From>
120requires byte_pointer<To> || byte_pointer<From>
122 constexpr bool is_const = std::is_const_v<std::remove_pointer_t<From>>;
123 using V = std::conditional_t<is_const, const void*, void*>;
124 return chain_cast<To, V>(
p);
128template<
typename To,
typename From>
130 byte_type<To> || char_type<To>
131 || byte_type<From> || char_type<From>
133 assert(!(
s.size() %
sizeof(To)));
134 return {byte_cast<To*>(
s.data()),
s.size() /
sizeof(To)};
139 return static_cast<std::underlying_type_t<T>
>(t);
143inline constexpr auto ptr_diff(
const auto *lhs,
const auto *rhs) {
144 return byte_cast<const char*>(lhs) - byte_cast<const char*>(rhs);
148inline constexpr bool ptr_cmp(
const auto *p0,
const auto *p1)
149 {
return static_cast<const void*
>(p0) ==
static_cast<const void*
>(p1); }
152template<standard_layout T>
155 return static_cast<std::size_t
>(
ptr_diff(&(t.*
p), &t));
158inline auto as_bytes(
const void *
p) {
return static_cast<const std::byte*
>(
p); }
159inline auto as_bytes(
void *
p) {
return static_cast<std::byte*
>(
p); }
161inline std::span<const std::byte>
as_byte_span(
const auto *x)
162 {
return {
as_bytes(x),
sizeof(*x)}; }
164 {
return {
as_bytes(x),
sizeof(*x)}; }
166inline constexpr bool str_less(
const char *lhs,
const char *rhs) {
167 if(!std::is_constant_evaluated())
168 return std::strcmp(lhs, rhs) < 0;
169 while(*lhs && *rhs && *lhs == *rhs)
171 return *rhs && (!*lhs || *lhs < *rhs);
174template<
typename To,
typename From>
176 sizeof(To) ==
sizeof(From)
177 && std::is_trivially_copyable_v<To>
178 && std::is_trivially_copyable_v<From>)
179constexpr auto bit_cast(
const From &from) {
180 static_assert(std::is_trivially_constructible_v<To>);
182 std::memcpy(&ret, &from,
sizeof(To));
187constexpr auto set_bit(
T t,
T mask,
bool value) {
188 assert(std::popcount(mask) == 1);
189 return t ^ ((t ^ -
T{value}) & mask);
197template<
typename>
struct member_obj_type;
199template<
typename T,
typename O>
200struct member_obj_type<O(
T::*)> : std::type_identity<T> {};
202template<
typename T,
typename R,
typename ...Args>
203struct member_obj_type<R(
T::*)(Args...)> : std::type_identity<T> {};
209template<member_po
inter auto p>
212 requires requires (
T t) { {t.*
p}; }
213 constexpr decltype(
auto)
operator()(
const T &t)
217template<member_po
inter auto p>
220 requires requires (
T t) { {t.*
p}; }
222 {
return lhs.*
p < rhs.*
p; }
229constexpr decltype(
auto)
rptr(
auto &&
r) {
return &
r; }
231bool read_file(std::string_view filename, std::string *ret);
232bool read_file(std::string_view filename, std::vector<std::byte> *ret);
assert
Definition: debug.lua:3
std::chrono::seconds s
Definition: timing.cpp:6
#define FWD(...)
Definition: utils.h:18
constexpr auto bit_cast(const From &from)
Definition: utils.h:179
constexpr To byte_cast(From p)
reinterpret_cast restricted to conversions from/to char/uchar.
Definition: utils.h:121
bool read_file(std::string_view filename, std::string *ret)
Definition: utils.cpp:30
constexpr auto to_underlying(T t)
Definition: utils.h:138
constexpr chain_cast(auto &&x)
Performs successive static_casts, right to left.
Definition: utils.h:95
constexpr rptr(auto &&r)
Allows passing an rvalue pointer to a function.
Definition: utils.h:229
constexpr auto set_bit(T t, T mask, bool value)
Definition: utils.h:187
constexpr bool str_less(const char *lhs, const char *rhs)
Definition: utils.h:166
constexpr cast(U &&x)
Cast value to T with the strictest cast operator.
Definition: utils.h:109
typename member_obj_type< T >::type member_obj_type_t
Definition: utils.h:207
constexpr bool ptr_cmp(const auto *p0, const auto *p1)
Compares the address of two pointers.
Definition: utils.h:148
To narrow(const From &x)
Casts x to a narrower type, asserting that the value is preserved.
Definition: utils.h:101
std::size_t offsetof_ptr(auto T::*p)
Similar to the stdlib's offsetof, but using member data pointers.
Definition: utils.h:153
std::span< const std::byte > as_byte_span(const auto *x)
Definition: utils.h:161
empty
Definition: utils.h:89
constexpr auto ptr_diff(const auto *lhs, const auto *rhs)
Signed distance in bytes between pointers.
Definition: utils.h:143
auto as_bytes(const void *p)
Definition: utils.h:158
constexpr bool operator()(const T &lhs, const T &rhs)
Definition: utils.h:221