virthttp  0.0
libvirt http interface
utility.hpp
Go to the documentation of this file.
1 //
2 // Created by _as on 2019-01-31.
3 //
4 
5 #pragma once
6 
7 #include <algorithm>
8 #include <cstdlib>
9 #include <optional>
10 #include <type_traits>
11 #include <gsl/gsl>
12 #include "cexpr_algs.hpp"
13 
14 #ifdef __GNUC__
15 #define UNREACHABLE __builtin_unreachable()
16 #elif _MSC_VER
17 #define UNREACHABLE __assume(0)
18 #else
19 #define UNREACHABLE
20 #endif
21 
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);
24 }
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; }
26 
27 class Empty {};
28 
29 template <class> struct RemoveOptional;
30 
31 template <class T> struct RemoveOptional<std::optional<T>> { using type = T; };
32 
33 template <class OptT> using RemoveOptional_t = typename RemoveOptional<OptT>::type;
34 
35 template <class... Ts> void sink(Ts&&... ts) { (static_cast<void>(std::move(ts)), ...); }
36 
37 template <class Lambda, class... Ts> constexpr auto test_sfinae(Lambda lambda, Ts&&...) -> decltype(lambda(std::declval<Ts>()...), bool{}) {
38  return true;
39 }
40 constexpr bool test_sfinae(...) { return false; }
41 
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))); }
43 
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>());
46 }
47 
48 template <typename T> using passive = T;
49 
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");
52  std::free(ptr);
53 }
54 
55 class EHTag {};
56 
57 template <class CRTP> class EnumHelper {
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; }
60 
61  constexpr static EHTag tag{};
62 
63  public:
64  [[nodiscard]] constexpr std::string_view to_string() const noexcept { return values()[to_integral(get_underlying(tag))]; }
65  [[nodiscard]] constexpr auto from_string_base(std::string_view v) const noexcept {
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;
68  }
69 };
70 
71 template <class CRTP> class EnumSetHelper {
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; }
74 
75  constexpr static EHTag tag{};
76 
77  public:
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))) -
80  1]; // C++2a: use std::countl_zeroe();
81  }
82  [[nodiscard]] constexpr auto from_string_base(std::string_view v) const noexcept {
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;
85  }
86 };
87 
88 template <class E, class = std::enable_if_t<std::is_base_of_v<EnumSetHelper<E>, E>>> E operator|(E lhs, E rhs) {
89  return {EHTag{}, to_integral(lhs) | to_integral(rhs)};
90 }
91 
92 template <class E, class = std::enable_if_t<std::is_base_of_v<EnumSetHelper<E>, E>>> E& operator|=(E& lhs, E rhs) {
93  return lhs = E{EHTag{}, to_integral(lhs) | to_integral(rhs)};
94 }
95 
96 template <class E> class EnumSetIterator {
97  using U = decltype(to_integral(std::declval<E>()));
98  E e;
99 
100  public:
101  explicit constexpr EnumSetIterator(E e) noexcept : e(e){};
102 
103  constexpr auto& operator++() noexcept {
104  const auto lz = __builtin_clz(to_integral(e));
105  const auto hi1b = sizeof(U) * 8 - lz - 1;
106  if (hi1b == -1)
107  e = E(0);
108  else
109  e = E(to_integral(e) &= ~(1 << hi1b));
110  return *this;
111  }
112 
113  constexpr E operator*() const noexcept {
114  const auto lz = __builtin_clz(to_integral(e));
115  const auto hi1b = sizeof(U) * 8 - lz - 1;
116  return 1u << hi1b;
117  }
118 
119  constexpr static EnumSetIterator end{E(0)};
120 };
121 
122 class alignas(alignof(char*)) UniqueZstring {
123  gsl::owner<char*> ptr{};
124 
125  public:
126  constexpr UniqueZstring() noexcept = default;
127  constexpr explicit UniqueZstring(gsl::owner<char*> ptr) : ptr(ptr) {}
128  constexpr explicit UniqueZstring(const UniqueZstring&) noexcept = delete;
129  inline UniqueZstring(UniqueZstring&& uz) noexcept : ptr(uz.ptr) { uz.ptr = nullptr; };
130  inline ~UniqueZstring() noexcept { std::free(ptr); }
131 
132  constexpr UniqueZstring& operator=(const UniqueZstring&) noexcept = delete;
133  inline UniqueZstring& operator=(UniqueZstring&& uz) noexcept {
134  this->~UniqueZstring();
135  ptr = uz.ptr;
136  uz.ptr = nullptr;
137  return *this;
138  };
139 
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(); }
144 
145  constexpr inline explicit operator const char*() const noexcept { return ptr; }
146  constexpr inline explicit operator char*() noexcept { return ptr; }
147 
148  constexpr inline explicit operator bool() const noexcept { return ptr; }
149 };
150 
151 namespace ext {
152 /* Function traits: */
153 // https://functionalcpp.wordpress.com/2013/08/05/function-traits/
154 
155 template <class F> struct function_traits;
156 
157 // function pointer
158 template <class R, class... Args> struct function_traits<R (*)(Args...)> : public function_traits<R(Args...)> {};
159 
160 template <class R, class... Args> struct function_traits<R(Args...)> {
161  using return_type = R;
162 
163  static constexpr std::size_t arity = sizeof...(Args);
164 
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;
168  };
169 
170  template <std::size_t N> using Arg_t = typename Arg<N>::type;
171 };
172 
173 // member function pointer
174 template <class C, class R, class... Args> struct function_traits<R (C::*)(Args...)> : public function_traits<R(C&, Args...)> {};
175 
176 // const member function pointer
177 template <class C, class R, class... Args> struct function_traits<R (C::*)(Args...) const> : public function_traits<R(C&, Args...)> {};
178 
179 // member object pointer
180 template <class C, class R> struct function_traits<R(C::*)> : public function_traits<R(C&)> {};
181 
182 // functor
183 template <class F> struct function_traits {
184  private:
186 
187  public:
189 
190  static constexpr std::size_t arity = call_type::arity - 1;
191 
192  template <std::size_t N> struct Arg {
193  static_assert(N < arity, "error: invalid parameter index.");
194  using type = typename call_type::template Arg<N + 1>::type;
195  };
196  template <std::size_t N> using Arg_t = typename Arg<N>::type;
197 };
198 
199 template <class F> struct function_traits<F&> : public function_traits<F> {};
200 
201 template <class F> struct function_traits<F&&> : public function_traits<F> {};
202 } // namespace ext
203 
204 /* */
205 template <typename T> struct NoallocWFree : private std::allocator<gsl::owner<T>> { // This clearly needs to be shadowed from the library users
206  using value_type = 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 {}
210  inline void destroy(gsl::owner<T>* ptr) const noexcept { freeany(*ptr); }
211 };
212 
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); }
219 };
220 
221 template <typename T, typename D> struct UniqueNullTerminatedSpan : public std::unique_ptr<T[], D> {
222  constexpr UniqueNullTerminatedSpan() noexcept = default;
223  UniqueNullTerminatedSpan(T* p, D d) noexcept : std::unique_ptr<T[], D>(p, d) {}
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(); }
228 };
229 
230 template <typename T, typename D> struct UniqueFalseTerminatedSpan : public std::unique_ptr<T[], D> {
231  private:
232  static constexpr auto false_it(T* arr) {
233  while (*arr)
234  ++arr;
235  return arr;
236  }
237 
238  public:
239  constexpr UniqueFalseTerminatedSpan() noexcept = default;
240  UniqueFalseTerminatedSpan(T* p, D d) noexcept : std::unique_ptr<T[], D>(p, d) {}
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()); }
245 };
246 
247 namespace virt::meta {
248 namespace impl::any {
249 // Need template lambdas to reduce bloat, as types need to be passed around
250 }
251 namespace light {
252 template <typename U, typename CF, typename DF> auto wrap_oparm_owning_fill_static_arr(U underlying, CF&& count_fcn, DF&& data_fcn) {
253  using CountFTraits = ext::function_traits<CF>;
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;
257 
258  using DataFTraits = ext::function_traits<DF>;
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>>;
265 
266  using RetType = std::optional<std::vector<T>>;
267  std::vector<T> ret{};
268  ret.resize(count_fcn(underlying));
269  if (!ret.empty()) {
270  const auto res = data_fcn(underlying, ret.data(), ret.size());
271  if (res <= 0)
272  return RetType{std::nullopt};
273  }
274  return RetType{ret};
275 }
276 template <typename U, typename CF, typename DF> auto wrap_oparm_owning_fill_freeable_arr(U underlying, CF count_fcn, DF data_fcn) {
277  using CountFTraits = ext::function_traits<CF>;
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;
281 
282  using DataFTraits = ext::function_traits<DF>;
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>>;
289 
290  using LocAlloc = NoallocWFree<T>;
291  using RetType = std::optional<std::vector<gsl::owner<T>, LocAlloc>>;
292  RetType ret{};
293  auto& vec = ret.emplace();
294  vec.resize(count_fcn(underlying));
295  if (!vec.empty()) {
296  const auto res = data_fcn(underlying, vec.data(), vec.size());
297  if (res != 0)
298  return RetType{std::nullopt};
299  }
300  return ret;
301 }
302 
303 template <typename Conv = void, typename U, typename CF, typename DF, typename... DF_Args>
304 auto wrap_oparm_owning_fill_autodestroyable_arr(U underlying, CF count_fcn, DF data_fcn, DF_Args... df_args) {
305  using CountFTraits = ext::function_traits<CF>;
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;
309 
310  using DataFTraits = ext::function_traits<DF>;
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>;
320 
321  using RetType = std::optional<std::vector<T>>;
322  RetType ret{};
323  auto& vec = ret.emplace();
324  vec.resize(count_fcn(underlying));
325  if (!vec.empty()) {
326  const auto res = data_fcn(underlying, reinterpret_cast<DedT*>(vec.data()), vec.size(), df_args...); // C++2a: std::bit_cast
327  if (res != 0)
328  return RetType{std::nullopt};
329  }
330  return ret;
331 }
332 
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>
335 decltype(auto) wrap_opram_owning_set_destroyable_arr(U underlying, DataFRet (*data_fcn)(U, T**, DataFArgs...), DataFArgs... data_f_args) {
336  Wrap* lease_arr;
337  auto res = data_fcn(underlying, reinterpret_cast<T**>(&lease_arr), data_f_args...);
338  auto deleter = [=](Wrap* arr) {
339  if (arr == nullptr)
340  return res;
341 
342  for (auto it = arr; it != arr + res; ++it)
343  dtroy(it);
344  freeany(arr);
345  return -1;
346  };
347  using RetType = Span<Wrap, std::conditional_t<std::is_same_v<Span<char, decltype(std::free)>, UniqueSpan<char, decltype(std::free)>>,
348  decltype(deleter), void (*)(Wrap*)>>;
349 
350  if constexpr (std::is_same_v<RetType, UniqueSpan<Wrap, decltype(deleter)>>) {
351  return RetType{res != -1 ? lease_arr : nullptr, deleter};
352  } else {
353  if (res == -1)
354  return RetType{nullptr, nullptr};
355  return RetType{lease_arr, [](auto arr) {
356  auto it = arr;
357  while (it)
358  dtroy(it++);
359  freeany(arr);
360  }};
361  }
362 }
363 } // namespace light
364 namespace heavy {
365 template <typename Conv = void, typename U, typename CountFRet, typename DataFRet, typename T>
366 auto wrap_oparm_owning_fill_static_arr(U underlying, CountFRet (*count_fcn)(U), DataFRet (*data_fcn)(U, T*, CountFRet)) {
367  std::vector<gsl::owner<T>> ret{};
368  ret.resize(count_fcn(underlying));
369  const auto res = data_fcn(underlying, ret.data(), ret.size());
370  if (res != 0)
371  throw std::runtime_error{__func__};
372  if constexpr (std::is_same_v<void, Conv>)
373  return ret;
374  std::vector<Conv> tret{};
375  tret.reserve(ret.size());
376  std::move(ret.begin(), ret.end(), std::back_inserter(tret));
377  return tret;
378 }
379 template <typename Conv = void, typename U, typename CF, typename DF>
380 auto wrap_oparm_owning_fill_freeable_arr(U underlying, CF count_fcn, DF data_fcn) {
381  using CountFTraits = ext::function_traits<CF>;
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;
385 
386  using DataFTraits = ext::function_traits<DF>;
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>>;
393 
394  using LocAlloc = NoallocWFree<T>;
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());
398  if (res != 0)
399  throw std::runtime_error{__func__};
400  if constexpr (std::is_same_v<void, Conv>)
401  return ret;
402  std::vector<Conv> tret{};
403  tret.reserve(ret.size());
404  std::move(ret.begin(), ret.end(), std::back_inserter(tret));
405  return tret;
406 }
407 
408 template <typename Conv = void, typename U, typename CF, typename DF>
409 auto wrap_oparm_owning_fill_autodestroyable_arr(U underlying, CF count_fcn, DF data_fcn) {
410  using CountFTraits = ext::function_traits<CF>;
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;
414 
415  using DataFTraits = ext::function_traits<DF>;
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>;
423 
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()); // C++2a: std::bit_cast
427  if (res != 0)
428  throw std::runtime_error{__func__};
429  if constexpr (std::is_same_v<void, Conv>)
430  return ret;
431  std::vector<Conv> tret{};
432  tret.reserve(ret.size());
433  std::move(ret.begin(), ret.end(), std::back_inserter(tret));
434  return tret;
435 }
436 
437 template <typename Wrap = void, typename U, typename DataFRet, typename T, typename... DataFArgs>
438 auto wrap_opram_owning_set_destroyable_arr(U underlying, DataFRet (*data_fcn)(U, T**, DataFArgs...), DataFArgs... data_f_args) {
439  T* ptr;
440  auto res = data_fcn(underlying, &ptr, data_f_args...);
441  if (res == -1)
442  throw std::runtime_error{__func__};
443  using ValueType = std::conditional_t<std::is_void_v<Wrap>, T, Wrap>;
444  std::vector<ValueType> ret;
445  ret.reserve(res);
446  auto it = ptr;
447  const auto end = ptr + res;
448  while (it != end)
449  ret.emplace_back(*it++);
450  freeany(ptr);
451  return ret;
452 }
453 } // namespace heavy
454 } // namespace virt::meta
455 
456 // From C++ Weekly - Ep 134 (Jason Turner) :
457 // https://www.youtube.com/watch?v=EsUmnLgz8QY
458 
459 template <typename... Base> struct Visitor : Base... { using Base::operator()...; };
460 
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
auto wrap_oparm_owning_fill_freeable_arr(U underlying, CF count_fcn, DF data_fcn)
Definition: utility.hpp:380
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
STL namespace.
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 wrap_oparm_owning_fill_static_arr(U underlying, CountFRet(*count_fcn)(U), DataFRet(*data_fcn)(U, T *, CountFRet))
Definition: utility.hpp:366
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
auto wrap_opram_owning_set_destroyable_arr(U underlying, DataFRet(*data_fcn)(U, T **, DataFArgs...), DataFArgs...data_f_args)
Definition: utility.hpp:438
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
auto wrap_oparm_owning_fill_autodestroyable_arr(U underlying, CF count_fcn, DF data_fcn)
Definition: utility.hpp:409
constexpr std::string_view to_string() const noexcept
Definition: utility.hpp:78
Definition: utility.hpp:205
auto cbegin() const noexcept
Definition: utility.hpp:243
Definition: utility.hpp:247
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