10 #include <type_traits> 15 #define UNREACHABLE __builtin_unreachable() 17 #define UNREACHABLE __assume(0) 22 template <
typename E, std::enable_if_t<std::is_enum_v<E>,
int> = 0> constexpr
inline decltype(
auto)
to_integral(E e) {
23 return static_cast<typename std::underlying_type<E>::type
>(e);
25 template <
typename T, std::enable_if_t<std::is_
integral_v<T>,
int> = 0> constexpr
inline decltype(
auto)
to_integral(T v) {
return v; }
35 template <
class... Ts>
void sink(Ts&&... ts) { (
static_cast<void>(std::move(ts)), ...); }
37 template <
class Lambda,
class... Ts> constexpr
auto test_sfinae(Lambda lambda, Ts&&...) -> decltype(lambda(std::declval<Ts>()...),
bool{}) {
42 template <
typename T,
typename V,
size_t... I>
void visit_impl(T&& t, V&& v, std::index_sequence<I...>) { (..., v(std::get<I>(t))); }
44 template <
typename T,
typename V>
void visit(T&& t, V&& v) {
45 visit_impl(std::forward<T>(t), std::forward<V>(v), std::make_index_sequence<std::tuple_size<
typename std::decay<T>::type>::value>());
50 template <
typename T>
inline void freeany(T ptr) {
51 static_assert(std::is_array_v<T> || std::is_pointer_v<T>,
"T needs to be a pointer or an array type");
58 constexpr
auto& get_underlying(
EHTag)
const noexcept {
return static_cast<const CRTP&
>(*this).underlying; }
59 constexpr
auto& values()
const noexcept {
return static_cast<const CRTP&
>(*this).values; }
61 constexpr
static EHTag tag{};
64 [[nodiscard]] constexpr std::string_view
to_string() const noexcept {
return values()[
to_integral(get_underlying(tag))]; }
66 const auto res =
cexpr::find(values().cbegin(), values().cend(), v);
67 return res != values().end() ? std::optional{CRTP{tag, std::distance(values().cbegin(), res)}} : std::nullopt;
72 constexpr
auto& get_underlying(
EHTag)
const noexcept {
return static_cast<const CRTP&
>(*this).underlying; }
73 constexpr
auto& values()
const noexcept {
return static_cast<const CRTP&
>(*this).values; }
75 constexpr
static EHTag tag{};
78 [[nodiscard]] constexpr std::string_view
to_string() const noexcept {
79 return values()[
sizeof(decltype(
to_integral(get_underlying(tag)))) * 8 - __builtin_clz(
to_integral(get_underlying(tag))) -
83 const auto res =
cexpr::find(values().cbegin(), values().end(), v);
84 return res != values().cend() ? std::optional{CRTP{tag, (1u << std::distance(values().cbegin(), res))}} : std::nullopt;
88 template <
class E,
class = std::enable_if_t<std::is_base_of_v<EnumSetHelper<E>, E>>> E
operator|(E lhs, E rhs) {
92 template <
class E,
class = std::enable_if_t<std::is_base_of_v<EnumSetHelper<E>, E>>> E&
operator|=(E& lhs, E rhs) {
105 const auto hi1b =
sizeof(U) * 8 - lz - 1;
115 const auto hi1b =
sizeof(U) * 8 - lz - 1;
123 gsl::owner<char*> ptr{};
140 [[nodiscard]]
inline auto begin() const noexcept {
return std::string_view{ptr}.begin(); }
141 [[nodiscard]]
inline auto end() const noexcept {
return std::string_view{ptr}.end(); }
142 [[nodiscard]]
inline auto cbegin() const noexcept {
return std::string_view{ptr}.cbegin(); }
143 [[nodiscard]]
inline auto cend() const noexcept {
return std::string_view{ptr}.cend(); }
145 constexpr
inline explicit operator const char*()
const noexcept {
return ptr; }
146 constexpr
inline explicit operator char*() noexcept {
return ptr; }
148 constexpr
inline explicit operator bool() const noexcept {
return ptr; }
163 static constexpr std::size_t arity =
sizeof...(Args);
165 template <std::
size_t N>
struct Arg {
166 static_assert(N < arity,
"error: invalid parameter index.");
167 using type =
typename std::tuple_element<N, std::tuple<Args...>>
::type;
190 static constexpr std::size_t arity = call_type::arity - 1;
192 template <std::
size_t N>
struct Arg {
193 static_assert(N < arity,
"error: invalid parameter index.");
196 template <std::
size_t N>
using Arg_t =
typename Arg<N>::type;
205 template <
typename T>
struct NoallocWFree :
private std::allocator<gsl::owner<T>> {
207 using std::allocator<gsl::owner<T>>::allocate;
208 using std::allocator<gsl::owner<T>>::deallocate;
209 constexpr
inline void construct(gsl::owner<T>* ptr)
const noexcept {}
213 template <
typename T,
typename D>
struct UniqueSpan : std::unique_ptr<T[], D> {
214 UniqueSpan(T* p, D d) noexcept : std::unique_ptr<T[], D>(p, d) {}
215 inline auto begin() const noexcept {
return this->
get(); }
216 inline auto end() const noexcept {
return this->
get() + this->get_deleter()(
nullptr); }
217 inline auto cbegin() const noexcept {
return this->
get(); }
218 inline auto cend() const noexcept {
return this->
get() + this->get_deleter()(
nullptr); }
224 inline auto begin() const noexcept {
return std::basic_string_view<T*>{this->
get()}.
begin(); }
225 inline auto end() const noexcept {
return std::basic_string_view<T*>{this->
get()}.
end(); }
226 inline auto cbegin() const noexcept {
return std::basic_string_view<T*>{this->
get()}.
cbegin(); }
227 inline auto cend() const noexcept {
return std::basic_string_view<T*>{this->
get()}.
cend(); }
232 static constexpr
auto false_it(T* arr) {
241 inline auto begin() const noexcept {
return this->
get(); }
242 inline auto end() const noexcept {
return false_it(this->
get()); }
243 inline auto cbegin() const noexcept {
return this->
get(); }
244 inline auto cend() const noexcept {
return false_it(this->
get()); }
248 namespace impl::any {
254 static_assert(CountFTraits::arity == 1,
"Counting function requires one argument");
255 static_assert(std::is_same_v<
typename CountFTraits::template Arg_t<0>, U>,
"Counting function requires the underlying ptr as argument");
256 using CountFRet =
typename CountFTraits::return_type;
259 static_assert(DataFTraits::arity == 3,
"Data function requires three arguments");
260 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<0>, U>,
"Data function requires the underlying ptr as first argument");
261 static_assert(std::is_pointer_v<
typename DataFTraits::template Arg_t<0>>,
"Data function requires a pointer to the array as second argument");
262 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<2>, CountFRet>,
263 "Data function requires counting function return type as third argument");
264 using T = std::remove_pointer_t<typename DataFTraits::template Arg_t<1>>;
266 using RetType = std::optional<std::vector<T>>;
267 std::vector<T> ret{};
268 ret.resize(count_fcn(underlying));
270 const auto res = data_fcn(underlying, ret.data(), ret.size());
272 return RetType{std::nullopt};
278 static_assert(CountFTraits::arity == 1,
"Counting function requires one argument");
279 static_assert(std::is_same_v<
typename CountFTraits::template Arg_t<0>, U>,
"Counting function requires the underlying ptr as argument");
280 using CountFRet =
typename CountFTraits::return_type;
283 static_assert(DataFTraits::arity == 3,
"Data function requires three arguments");
284 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<0>, U>,
"Data function requires the underlying ptr as first argument");
285 static_assert(std::is_pointer_v<
typename DataFTraits::template Arg_t<0>>,
"Data function requires a pointer to the array as second argument");
286 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<2>, CountFRet>,
287 "Data function requires counting function return type as third argument");
288 using T = std::remove_pointer_t<typename DataFTraits::template Arg_t<1>>;
291 using RetType = std::optional<std::vector<gsl::owner<T>, LocAlloc>>;
293 auto& vec = ret.emplace();
294 vec.resize(count_fcn(underlying));
296 const auto res = data_fcn(underlying, vec.data(), vec.size());
298 return RetType{std::nullopt};
303 template <
typename Conv = void,
typename U,
typename CF,
typename DF,
typename... DF_Args>
306 static_assert(CountFTraits::arity == 1,
"Counting function requires one argument");
307 static_assert(std::is_same_v<
typename CountFTraits::template Arg_t<0>, U>,
"Counting function requires the underlying ptr as argument");
308 using CountFRet =
typename CountFTraits::return_type;
311 static_assert(DataFTraits::arity == 3 +
sizeof...(DF_Args),
"Data function requires three base arguments");
312 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<0>, U>,
"Data function requires the underlying ptr as first argument");
313 static_assert(std::is_pointer_v<
typename DataFTraits::template Arg_t<0>>,
"Data function requires a pointer to the array as second argument");
314 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<2>, CountFRet>,
315 "Data function requires counting function return type as third argument");
316 using DedT = std::remove_pointer_t<typename DataFTraits::template Arg_t<1>>;
317 if constexpr (!std::is_same_v<Conv, void>)
318 static_assert(
sizeof(DedT) ==
sizeof(Conv) &&
alignof(DedT) ==
alignof(Conv),
"Conversion type must have the same size as the source");
319 using T = std::conditional_t<std::is_same_v<Conv, void>, DedT, Conv>;
321 using RetType = std::optional<std::vector<T>>;
323 auto& vec = ret.emplace();
324 vec.resize(count_fcn(underlying));
326 const auto res = data_fcn(underlying, reinterpret_cast<DedT*>(vec.data()), vec.size(), df_args...);
328 return RetType{std::nullopt};
333 template <
typename Wrap,
template <
class,
class>
typename Span =
UniqueSpan, void (*dtroy)(Wrap*) = std::destroy_at<Wrap>,
typename U,
334 typename DataFRet,
typename T,
typename... DataFArgs>
337 auto res = data_fcn(underlying, reinterpret_cast<T**>(&lease_arr), data_f_args...);
338 auto deleter = [=](Wrap* arr) {
342 for (
auto it = arr; it != arr + res; ++it)
348 decltype(deleter), void (*)(Wrap*)>>;
350 if constexpr (std::is_same_v<RetType,
UniqueSpan<Wrap, decltype(deleter)>>) {
351 return RetType{res != -1 ? lease_arr :
nullptr, deleter};
354 return RetType{
nullptr,
nullptr};
355 return RetType{lease_arr, [](
auto arr) {
365 template <
typename Conv =
void,
typename U,
typename CountFRet,
typename DataFRet,
typename T>
367 std::vector<gsl::owner<T>> ret{};
368 ret.resize(count_fcn(underlying));
369 const auto res = data_fcn(underlying, ret.data(), ret.size());
371 throw std::runtime_error{__func__};
372 if constexpr (std::is_same_v<void, Conv>)
374 std::vector<Conv> tret{};
375 tret.reserve(ret.size());
376 std::move(ret.begin(), ret.end(), std::back_inserter(tret));
379 template <
typename Conv =
void,
typename U,
typename CF,
typename DF>
382 static_assert(CountFTraits::arity == 1,
"Counting function requires one argument");
383 static_assert(std::is_same_v<
typename CountFTraits::template Arg_t<0>, U>,
"Counting function requires the underlying ptr as argument");
384 using CountFRet =
typename CountFTraits::return_type;
387 static_assert(DataFTraits::arity == 3,
"Data function requires three arguments");
388 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<0>, U>,
"Data function requires the underlying ptr as first argument");
389 static_assert(std::is_pointer_v<
typename DataFTraits::template Arg_t<0>>,
"Data function requires a pointer to the array as second argument");
390 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<2>, CountFRet>,
391 "Data function requires counting function return type as third argument");
392 using T = std::remove_pointer_t<typename DataFTraits::template Arg_t<1>>;
395 std::vector<gsl::owner<T>, LocAlloc> ret{};
396 ret.resize(count_fcn(underlying));
397 const auto res = data_fcn(underlying, ret.data(), ret.size());
399 throw std::runtime_error{__func__};
400 if constexpr (std::is_same_v<void, Conv>)
402 std::vector<Conv> tret{};
403 tret.reserve(ret.size());
404 std::move(ret.begin(), ret.end(), std::back_inserter(tret));
408 template <
typename Conv =
void,
typename U,
typename CF,
typename DF>
411 static_assert(CountFTraits::arity == 1,
"Counting function requires one argument");
412 static_assert(std::is_same_v<
typename CountFTraits::template Arg_t<0>, U>,
"Counting function requires the underlying ptr as argument");
413 using CountFRet =
typename CountFTraits::return_type;
416 static_assert(DataFTraits::arity == 3,
"Data function requires three arguments");
417 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<0>, U>,
"Data function requires the underlying ptr as first argument");
418 static_assert(std::is_pointer_v<
typename DataFTraits::template Arg_t<0>>,
"Data function requires a pointer to the array as second argument");
419 static_assert(std::is_same_v<
typename DataFTraits::template Arg_t<2>, CountFRet>,
420 "Data function requires counting function return type as third argument");
421 using DedT = std::remove_pointer_t<typename DataFTraits::template Arg_t<1>>;
422 using T = std::conditional_t<(sizeof(DedT) == sizeof(Conv) && alignof(DedT) == alignof(Conv)), Conv, DedT>;
424 std::vector<T> ret{};
425 ret.resize(count_fcn(underlying));
426 const auto res = data_fcn(underlying, reinterpret_cast<DedT*>(ret.data()), ret.size());
428 throw std::runtime_error{__func__};
429 if constexpr (std::is_same_v<void, Conv>)
431 std::vector<Conv> tret{};
432 tret.reserve(ret.size());
433 std::move(ret.begin(), ret.end(), std::back_inserter(tret));
437 template <
typename Wrap = void,
typename U,
typename DataFRet,
typename T,
typename... DataFArgs>
440 auto res = data_fcn(underlying, &ptr, data_f_args...);
442 throw std::runtime_error{__func__};
443 using ValueType = std::conditional_t<std::is_void_v<Wrap>, T, Wrap>;
444 std::vector<ValueType> ret;
447 const auto end = ptr + res;
449 ret.emplace_back(*it++);
459 template <
typename... Base>
struct Visitor : Base... {
using Base::operator()...; };
461 template <
typename... T>
Visitor(T...)->Visitor<T...>;
auto cend() const noexcept
Definition: utility.hpp:244
void freeany(T ptr)
Definition: utility.hpp:50
typename Arg< N >::type Arg_t
Definition: utility.hpp:196
void sink(Ts &&...ts)
Definition: utility.hpp:35
UniqueFalseTerminatedSpan(T *p, D d) noexcept
Definition: utility.hpp:240
UniqueZstring(UniqueZstring &&uz) noexcept
Definition: utility.hpp:129
constexpr auto & operator++() noexcept
Definition: utility.hpp:103
void destroy(gsl::owner< T > *ptr) const noexcept
Definition: utility.hpp:210
Definition: utility.hpp:55
UniqueSpan(T *p, D d) noexcept
Definition: utility.hpp:214
auto begin() const noexcept
Definition: utility.hpp:241
auto begin() const noexcept
Definition: utility.hpp:224
auto end() const noexcept
Definition: utility.hpp:141
auto end() const noexcept
Definition: utility.hpp:216
auto cend() const noexcept
Definition: utility.hpp:143
typename Arg< N >::type Arg_t
Definition: utility.hpp:170
auto cend() const noexcept
Definition: utility.hpp:218
auto cbegin() const noexcept
Definition: utility.hpp:226
T passive
Definition: utility.hpp:48
Definition: utility.hpp:96
gsl::owner< T > value_type
Definition: utility.hpp:206
constexpr EnumSetIterator(E e) noexcept
Definition: utility.hpp:101
constexpr auto from_string_base(std::string_view v) const noexcept
Definition: utility.hpp:65
auto cbegin() const noexcept
Definition: utility.hpp:142
constexpr void construct(gsl::owner< T > *ptr) const noexcept
Definition: utility.hpp:209
Definition: utility.hpp:230
typename call_type::return_type return_type
Definition: utility.hpp:188
Definition: utility.hpp:213
constexpr auto from_string_base(std::string_view v) const noexcept
Definition: utility.hpp:82
Visitor(T...) -> Visitor< T... >
UniqueNullTerminatedSpan(T *p, D d) noexcept
Definition: utility.hpp:223
R return_type
Definition: utility.hpp:161
Definition: utility.hpp:71
constexpr auto test_sfinae(Lambda lambda, Ts &&...) -> decltype(lambda(std::declval< Ts >()...), bool
Definition: utility.hpp:37
auto end() const noexcept
Definition: utility.hpp:225
Definition: utility.hpp:122
typename std::tuple_element< N, std::tuple< Args... >>::type type
Definition: utility.hpp:167
E & operator|=(E &lhs, E rhs)
Definition: utility.hpp:92
Definition: utility.hpp:459
~UniqueZstring() noexcept
Definition: utility.hpp:130
typename RemoveOptional< OptT >::type RemoveOptional_t
Definition: utility.hpp:33
E operator|(E lhs, E rhs)
Definition: utility.hpp:88
auto cbegin() const noexcept
Definition: utility.hpp:217
constexpr UniqueZstring(gsl::owner< char * > ptr)
Definition: utility.hpp:127
auto begin() const noexcept
Definition: utility.hpp:140
void visit_impl(T &&t, V &&v, std::index_sequence< I... >)
Definition: utility.hpp:42
Definition: utility.hpp:221
constexpr std::string_view to_string() const noexcept
Definition: utility.hpp:64
Definition: utility.hpp:192
constexpr E operator*() const noexcept
Definition: utility.hpp:113
constexpr InputIt find(InputIt first, InputIt last, const T &value)
Definition: cexpr_algs.hpp:4
UniqueZstring & operator=(UniqueZstring &&uz) noexcept
Definition: utility.hpp:133
Definition: utility.hpp:155
Definition: utility.hpp:27
decltype(auto) constexpr to_integral(E e)
Definition: utility.hpp:22
T type
Definition: utility.hpp:31
auto begin() const noexcept
Definition: utility.hpp:215
constexpr std::string_view to_string() const noexcept
Definition: utility.hpp:78
Definition: utility.hpp:205
auto cbegin() const noexcept
Definition: utility.hpp:243
void visit(T &&t, V &&v)
Definition: utility.hpp:44
Definition: utility.hpp:151
Definition: utility.hpp:29
typename call_type::template Arg< N+1 >::type type
Definition: utility.hpp:194
Definition: utility.hpp:57
auto cend() const noexcept
Definition: utility.hpp:227
auto end() const noexcept
Definition: utility.hpp:242