kblib  0.2.3
General utilities library for modern C++
poly_obj.h
Go to the documentation of this file.
1 /* *****************************************************************************
2  * kblib is a general utility library for C++14 and C++17, intended to provide
3  * performant high-level abstractions and more expressive ways to do simple
4  * things.
5  *
6  * Copyright (c) 2021 killerbee
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  * ****************************************************************************/
21 
32 #ifndef POLY_OBJ_H
33 #define POLY_OBJ_H
34 
35 #include "hash.h"
36 #include "variant.h"
37 
38 namespace kblib {
39 
40 enum class construct_type : unsigned {
41  none = 0,
42  copy_only = 1,
43  move = 2,
44  both = 3,
45  throw_move = 4,
46  both_throw = 5,
47 };
49  construct_type r) noexcept
50  -> construct_type {
51  return static_cast<construct_type>(etoi(l) | etoi(r));
52 }
53 
55  construct_type r) noexcept
56  -> construct_type {
57  return static_cast<construct_type>(etoi(l) & etoi(r));
58 }
59 
60 KBLIB_NODISCARD constexpr auto operator*(construct_type l, bool r) noexcept
61  -> construct_type {
62  return r ? l : construct_type::none;
63 }
64 
70 namespace detail_poly {
71 
72  KBLIB_NODISCARD constexpr auto copyable(construct_type type) noexcept
73  -> bool {
75  }
76  KBLIB_NODISCARD constexpr auto movable(construct_type type) noexcept
77  -> bool {
78  return (type & construct_type::move) != construct_type::none;
79  }
80  KBLIB_NODISCARD constexpr auto nothrow_movable(construct_type type) noexcept
81  -> bool {
84  }
85 
86  KBLIB_NODISCARD constexpr auto make_ctype(bool copyable, bool movable,
87  bool nothrow_movable)
88  -> construct_type {
89  if (copyable) {
90  if (not movable) {
92  } else if (nothrow_movable) {
93  return construct_type::both;
94  } else {
96  }
97  } else if (movable) {
98  return construct_type::move;
99  } else {
100  return construct_type::none;
101  }
102  }
103 
104  template <construct_type traits>
106 
107  template <>
109  construct_conditional() noexcept = default;
112 
113  auto operator=(const construct_conditional&)
114  -> construct_conditional& = default;
115  auto operator=(construct_conditional&&)
116  -> construct_conditional& = default;
117  ~construct_conditional() = default;
118  };
119 
120  template <>
122  construct_conditional() noexcept = default;
123  construct_conditional(const construct_conditional&) noexcept = default;
125 
126  auto operator=(const construct_conditional&)
127  -> construct_conditional& = default;
128  auto operator=(construct_conditional&&)
129  -> construct_conditional& = default;
130  ~construct_conditional() = default;
131  };
132 
133  template <>
135  construct_conditional() noexcept = default;
136  construct_conditional(const construct_conditional&) noexcept = delete;
138 
139  auto operator=(const construct_conditional&)
140  -> construct_conditional& = default;
141  auto operator=(construct_conditional&&)
142  -> construct_conditional& = default;
143  ~construct_conditional() = default;
144  };
145 
146  template <>
148 
149  template <>
151  construct_conditional() noexcept = default;
152  construct_conditional(const construct_conditional&) noexcept = delete;
154 
156  -> construct_conditional& = default;
158  -> construct_conditional& = default;
160  };
161 
162  template <>
164  construct_conditional() noexcept = default;
167 
169  -> construct_conditional& = default;
171  -> construct_conditional& = default;
173  };
174 
175  template <typename T>
177  = construct_type::copy_only* std::is_copy_constructible<T>::value
178  | construct_type::move* std::is_move_constructible<T>::value
180  std::is_move_constructible<T>::value
181  & not std::is_nothrow_move_constructible<T>::value);
182 
183  template <typename T, typename hash = void>
184  struct erased_hash_t {};
185 
186  template <typename T>
187  struct erased_hash_t<T, void_t<fakestd::invoke_result_t<std::hash<T>, T>>> {
188  static auto default_hash(void* obj) -> std::size_t {
189  return std::hash<T>()(*static_cast<const T*>(obj));
190  }
191 
192  alias<std::size_t (*)(void*)> hash = &default_hash;
193  };
194 
195  template <typename T, typename hash = void>
197 
198  template <typename T>
200  T, void_t<fakestd::invoke_result_t<std::hash<T>, T>>> {
201  static auto default_hash(void* obj) -> std::size_t {
202  return FNV_hash<T>{}(*static_cast<const T*>(obj));
203  }
204 
205  alias<std::size_t (*)(void*)> hash = &default_hash;
206  };
207 
208  template <typename Traits>
210  : Traits::copy_t
211  , Traits::move_t
212  , Traits::destroy_t {
213  using Traits::copy_t::copy;
214  using Traits::move_t::move;
215 
216  using Traits::destroy_t::destroy;
217  };
218 
219  template <typename T, typename Traits>
220  KBLIB_NODISCARD auto make_ops_t() noexcept -> erased_construct<Traits> {
221  static_assert(implies<Traits::copyable,
222  std::is_copy_constructible<T>::value>::value,
223  "T must be copy constructible if Traits is.");
224  static_assert(
226  std::is_nothrow_move_constructible<T>::value>::value,
227  "T must be nothrow move constructible if Traits is.");
228  static_assert(
229  implies<Traits::movable, std::is_move_constructible<T>::value>::value,
230  "T must be move constructible if Traits is.");
231  return {{typename Traits::copy_t{static_cast<T*>(nullptr)}},
232  {typename Traits::move_t{static_cast<T*>(nullptr)}},
233  {typename Traits::destroy_t{static_cast<T*>(nullptr)}}};
234  }
235 
236  template <typename T, typename = void>
238  : std::integral_constant<std::size_t, sizeof(T)> {};
239  template <typename T>
240  struct extract_derived_size<T, void_if_t<(T::max_derived_size > sizeof(T))>>
241  : std::integral_constant<std::size_t, T::max_derived_size> {};
242 
243 } // namespace detail_poly
244 
246 template <typename T>
247 inline auto noop(void*, const T*) -> T* {
248  return nullptr;
249 }
251 template <typename T, bool nothrow>
252 inline auto noop(void*, T*) noexcept(nothrow) -> T* {
253  return nullptr;
254 }
256 template <typename Obj, bool copyable>
257 struct default_copy {
258  private:
259  template <typename T>
260  static auto do_copy(void* dest, const Obj* from) -> Obj* {
261  return static_cast<Obj*>(new (dest) T(*static_cast<const T*>(from)));
262  }
263 
264  auto (*p_copy)(void* dest, const Obj* from) -> Obj* = &noop<Obj>;
265 
266  public:
268  default_copy() noexcept = default;
270  template <typename T>
271  explicit default_copy(T*) noexcept
272  : p_copy(&do_copy<T>) {}
273 
275  KBLIB_NODISCARD auto copy(void* dest, const Obj* from) -> Obj* {
276  return p_copy(dest, from);
277  }
278 };
279 template <typename Obj>
280 struct default_copy<Obj, false> {
281  default_copy() noexcept = default;
282  template <typename T>
283  explicit default_copy(T*) noexcept {}
284  auto copy(void* dest, const Obj* from) -> Obj* = delete;
285 };
290 template <typename Obj, auto (Obj::*clone)(void*) const->Obj*>
291 struct clone_copy {
293  clone_copy() = default;
295  template <typename T>
296  clone_copy(T*) {}
297 
299  KBLIB_NODISCARD auto copy(void* dest, const Obj* from) -> Obj* {
300  return (from->*clone)(dest);
301  }
302 };
304 template <typename Obj, bool movable, bool nothrow, bool copyable>
305 struct default_move {
306  private:
307  template <typename T>
308  static auto do_move(void* dest, Obj* from) noexcept(nothrow) -> Obj* {
309  return static_cast<Obj*>(new (dest) T(std::move(*static_cast<T*>(from))));
310  }
311  // noexcept isn't working here on clang
312  auto (*p_move)(void* dest, Obj* from) noexcept(false)
313  -> Obj* = &noop<Obj, nothrow>;
314 
315  public:
317  default_move() noexcept = default;
319  template <typename T>
320  explicit default_move(T*) noexcept
321  : p_move(&do_move<T>) {}
322 
324  KBLIB_NODISCARD auto move(void* dest, Obj* from) noexcept(nothrow) -> Obj* {
325  return p_move(dest, from);
326  }
327 };
328 template <typename Obj, bool nothrow>
329 struct default_move<Obj, false, nothrow, false> {
330  default_move() noexcept = default;
331  template <typename T>
332  explicit default_move(T*) noexcept {}
333  auto move(void* dest, Obj* from) noexcept(nothrow) -> Obj* = delete;
334 };
335 // fallback on copy
336 template <typename Obj, bool nothrow>
337 struct default_move<Obj, false, nothrow, true>
338  : private default_copy<Obj, true> {
340 
341  KBLIB_NODISCARD auto move(void* dest, const Obj* from) noexcept(nothrow)
342  -> Obj* {
343  return this->copy(dest, from);
344  }
345 };
349 template <typename Obj>
351  default_destroy() noexcept = default;
352  template <typename T>
353  explicit default_destroy(T*) noexcept {}
354 
355  auto destroy(Obj* obj) -> void { obj->~Obj(); }
356  static_assert(std::has_virtual_destructor<Obj>::value,
357  "Obj must have a virtual destructor");
358 };
359 
360 // TODO(killerbee13): Distinguish between pointers to T and to
361 // most-derived-object
362 
372 template <typename Obj,
373  construct_type CType = detail_poly::construct_traits<Obj>>
375 
382  constexpr static std::size_t default_capacity
384 
388  constexpr static std::size_t alignment
389  = std::max(alignof(Obj), alignof(std::max_align_t));
390 
394  constexpr static bool copyable = detail_poly::copyable(CType);
395 
399  constexpr static bool movable = detail_poly::movable(CType);
403  constexpr static bool nothrow_movable = detail_poly::nothrow_movable(CType);
404 
418 
433 
448  static_assert(std::is_empty<destroy_t>::value, "");
449 };
450 
451 template <typename Obj>
453 template <typename Obj>
455 
476 template <typename Obj, std::size_t Capacity = 0,
477  typename Traits = poly_obj_traits<Obj>>
478 class poly_obj
479  : private detail_poly::construct_conditional<detail_poly::make_ctype(
480  Traits::copyable, Traits::movable, Traits::nothrow_movable)>
481  , private detail_poly::erased_construct<Traits> {
482  private:
486 
487  public:
491  static constexpr std::size_t capacity
492  = Capacity > 0 ? Capacity : Traits::default_capacity;
493 
494  static_assert(capacity >= sizeof(Obj),
495  "Capacity must be large enough for the object type.");
496  static_assert(not std::is_array<Obj>::value,
497  "poly_obj of array type is disallowed.");
498 
499  using base_type = Obj;
500  using traits_type = Traits;
501 
506 
509  constexpr poly_obj() = default;
513  constexpr poly_obj(std::nullptr_t) noexcept
514  : poly_obj() {}
522  constexpr poly_obj(const Obj& obj)
523  : ptr(new (data) Obj(obj)) {}
531  constexpr poly_obj(Obj&& obj) noexcept(Traits::nothrow_movable)
532  : ptr(new (data) Obj(std::move(obj))) {}
533 
540  template <typename... Args,
541  typename std::enable_if_t<
542  std::is_constructible<Obj, Args...>::value, int> = 0>
543  constexpr explicit poly_obj(fakestd::in_place_t, Args&&... args) noexcept(
544  std::is_nothrow_constructible<Obj, Args&&...>::value)
545  : ops_t(detail_poly::make_ops_t<Obj, Traits>())
546  , ptr(new (data) Obj(std::forward<Args>(args)...)) {}
547 
554  template <typename... Args,
555  typename std::enable_if_t<
556  std::is_constructible<Obj, Args...>::value, int> = 0>
557  constexpr explicit poly_obj(kblib::in_place_agg_t, Args&&... args) noexcept(
558  std::is_nothrow_constructible<Obj, Args&&...>::value)
559  : ops_t(detail_poly::make_ops_t<Obj, Traits>())
560  , ptr(new (data) Obj{std::forward<Args>(args)...}) {}
561 
574  template <typename U, typename... Args>
575  KBLIB_NODISCARD static auto make(Args&&... args) noexcept(
576  std::is_nothrow_constructible<U, Args&&...>::value) -> poly_obj {
577  static_assert(sizeof(U) <= capacity,
578  "U must fit inside of the inline capacity.");
579  static_assert(alignof(U) <= Traits::alignment,
580  "U must be no more aligned than Traits::alignment");
581  static_assert(std::is_base_of<Obj, U>::value
582  and std::is_convertible<U*, Obj*>::value,
583  "Obj must be an accessible base of Obj.");
584  static_assert(
586  std::is_copy_constructible<U>::value>::value,
587  "U must be copy constructible if Traits::copyable is true.");
588  static_assert(
589  implies<Traits::movable, std::is_move_constructible<U>::value>::value,
590  "U must be move constructible if Traits::movable is true.");
591  return {tag<U>{}, std::forward<Args>(args)...};
592  }
593 
606  template <typename U, typename... Args>
607  KBLIB_NODISCARD static auto make_aggregate(Args&&... args) noexcept(
608  std::is_nothrow_constructible<U, Args&&...>::value) -> poly_obj {
609  static_assert(sizeof(U) <= capacity,
610  "U must fit inside of the inline capacity.");
611  static_assert(alignof(U) <= Traits::alignment,
612  "U must be no more aligned than Traits::alignment");
613  static_assert(std::is_base_of<Obj, U>::value
614  and std::is_convertible<U*, Obj*>::value,
615  "Obj must be an accessible base of Obj.");
616  static_assert(
618  std::is_copy_constructible<U>::value>::value,
619  "U must be copy constructible if Traits::copyable is true.");
620  static_assert(
621  implies<Traits::movable, std::is_move_constructible<U>::value>::value,
622  "U must be move constructible if Traits::movable is true.");
623  return {tag<U, true>{}, std::forward<Args>(args)...};
624  }
626 
631 
638  constexpr poly_obj(const poly_obj& other)
639  : disabler(other)
640  , ops_t(other) {
641  if (other.ptr) {
642  ptr = this->copy(data, other.ptr);
643  }
644  }
653  constexpr poly_obj(poly_obj&& other) noexcept(Traits::nothrow_movable)
654  : disabler(std::move(other))
655  , ops_t(std::move(other)) {
656  if (other.ptr) {
657  ptr = this->move(data, other.ptr);
658  }
659  }
660 
671  auto operator=(const poly_obj& other) & -> poly_obj& {
672  if (this == &other) {
673  return *this;
674  }
675  clear();
676  static_cast<ops_t&>(*this) = other;
677  if (other.ptr) {
678  ptr = this->copy(data, other.ptr);
679  }
680  return *this;
681  }
682 
693  auto operator=(poly_obj&& other) & noexcept(Traits::nothrow_movable)
694  -> poly_obj& {
695  if (this == &other) {
696  return *this;
697  }
698  clear();
699  static_cast<ops_t&>(*this) = other;
700  if (other.ptr) {
701  ptr = this->move(data, other.ptr);
702  }
703  return *this;
704  }
706 
712  KBLIB_NODISCARD auto has_value() const& noexcept -> bool { return ptr; }
713 
714  explicit operator bool() const& noexcept { return has_value(); }
716 
721 
724  auto clear() noexcept -> void {
725  if (ptr) {
726  this->destroy(ptr);
727  ptr = nullptr;
728  }
729  static_cast<ops_t&>(*this) = {};
730  }
731 
732  ~poly_obj() noexcept {
733  if (ptr) {
734  this->destroy(ptr);
735  }
736  }
738 
744 
754  KBLIB_NODISCARD auto operator*() & noexcept -> Obj& { return *get(); }
765  KBLIB_NODISCARD auto operator*() const& noexcept -> const Obj& {
766  return *get();
767  }
779  -> Obj&& {
780  return std::move(*get());
781  }
795  KBLIB_NODISCARD auto operator*() const&& noexcept(Traits::nothrow_movable)
796  -> const Obj&& {
797  return std::move(*get());
798  }
799 
809  KBLIB_NODISCARD auto get() & noexcept -> Obj* { return ptr; }
819  KBLIB_NODISCARD auto get() const& noexcept -> const Obj* { return ptr; }
820 
830  KBLIB_NODISCARD auto operator->() & noexcept -> Obj* { return ptr; }
840  KBLIB_NODISCARD auto operator->() const& noexcept -> const Obj* {
841  return ptr;
842  }
843 
854  template <typename... Args>
855  auto operator()(Args&&... args) noexcept(
857  -> fakestd::invoke_result_t<Obj&, Args&&...> {
858  return kblib::invoke(*get(), std::forward<Args>(args)...);
859  }
870  template <typename... Args>
871  auto operator()(Args&&... args) const
873  -> fakestd::invoke_result_t<const Obj&, Args&&...> {
874  return kblib::invoke(*get(), std::forward<Args>(args)...);
875  }
876 
880  template <typename member_type>
882  member_type>&
883  operator->*(member_type Obj::*member) & noexcept {
884  return get()->*member;
885  }
886 
890  template <typename member_type>
891  const enable_if_t<
892  not std::is_member_function_pointer<member_type Obj::*>::value,
893  member_type>&
894  operator->*(member_type Obj::*member) const& noexcept {
895  return get()->*member;
896  }
897 
901  template <typename member_type>
903  member_type>&&
904  operator->*(member_type Obj::*member) && noexcept {
905  return std::move(get()->*member);
906  }
907 
911  template <typename member_type>
912  const enable_if_t<
913  not std::is_member_function_pointer<member_type Obj::*>::value,
914  member_type>&&
915  operator->*(member_type Obj::*member) const&& noexcept {
916  return std::move(get()->*member);
917  }
918 
923  template <typename member_type, typename... Args>
925  member_type (Obj::*member)(Args...)) & noexcept {
926  return [member, value = get()](Args... args) -> decltype(auto) {
927  return (value->*member)(std::forward<Args>(args)...);
928  };
929  }
930 
935  template <typename member_type, typename... Args>
936  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
937  const) & noexcept {
938  return [member, value = get()](Args... args) -> decltype(auto) {
939  return (value->*member)(std::forward<Args>(args)...);
940  };
941  }
942 
947  template <typename member_type, typename... Args>
948  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
949  const) const& noexcept {
950  return [member, value = get()](Args... args) -> decltype(auto) {
951  return (value->*member)(std::forward<Args>(args)...);
952  };
953  }
954 
959  template <typename member_type, typename... Args>
960  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
961  const) && noexcept {
962  return [member, value = get()](Args... args) -> decltype(auto) {
963  return (value->*member)(std::forward<Args>(args)...);
964  };
965  }
966 
971  template <typename member_type, typename... Args>
973  member_type (Obj::*member)(Args...) &) & noexcept {
974  return [member, value = get()](Args... args) -> decltype(auto) {
975  return (value->*member)(std::forward<Args>(args)...);
976  };
977  }
978 
983  template <typename member_type, typename... Args>
984  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
985  const&) & noexcept {
986  return [member, value = get()](Args... args) -> decltype(auto) {
987  return (value->*member)(std::forward<Args>(args)...);
988  };
989  }
990 
995  template <typename member_type, typename... Args>
996  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
997  const&) const& noexcept {
998  return [member, value = get()](Args... args) -> decltype(auto) {
999  return (value->*member)(std::forward<Args>(args)...);
1000  };
1001  }
1002 
1007  template <typename member_type, typename... Args>
1008  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
1009  &&) && noexcept {
1010  return [member, value = get()](Args... args) -> decltype(auto) {
1011  return (std::move(*value).*member)(std::forward<Args>(args)...);
1012  };
1013  }
1014 
1019  template <typename member_type, typename... Args>
1020  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
1021  const&) && noexcept {
1022  return [member, value = get()](Args... args) -> decltype(auto) {
1023  return (value->*member)(std::forward<Args>(args)...);
1024  };
1025  }
1026 
1031  template <typename member_type, typename... Args>
1033  member_type (Obj::*member)(Args...)) && noexcept {
1034  return [member, value = get()](Args... args) -> decltype(auto) {
1035  return (value->*member)(std::forward<Args>(args)...);
1036  };
1037  }
1038 
1043  template <typename member_type, typename... Args>
1044  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
1045  const&&) && noexcept {
1046  return [member, value = get()](Args... args) -> decltype(auto) {
1047  return (std::move(*value).*member)(std::forward<Args>(args)...);
1048  };
1049  }
1050 
1055  template <typename member_type, typename... Args>
1056  KBLIB_NODISCARD auto operator->*(member_type (Obj::*member)(Args...)
1057  const&&) const&& noexcept {
1058  return [member, value = get()](Args... args) -> decltype(auto) {
1059  return (std::move(*value).*member)(std::forward<Args>(args)...);
1060  };
1061  }
1062 
1063  private:
1064  alignas(Traits::alignment) byte data[capacity]{};
1065  Obj* ptr{};
1066 
1067  template <typename U, bool = false>
1068  struct tag {};
1069 
1070  template <typename U, typename... Args>
1071  poly_obj(tag<U>, Args&&... args) noexcept(
1072  std::is_nothrow_constructible<U, Args&&...>::value)
1073  : ops_t(detail_poly::make_ops_t<U, Traits>())
1074  , ptr(new (data) U(std::forward<Args>(args)...)) {}
1075 
1076  template <typename U, typename... Args>
1077  poly_obj(tag<U, true>, Args&&... args) noexcept(
1078  std::is_nothrow_constructible<U, Args&&...>::value)
1079  : ops_t(detail_poly::make_ops_t<U, Traits>())
1080  , ptr(new (data) U{std::forward<Args>(args)...}) {}
1081 };
1082 
1083 template <bool warn>
1084 constexpr auto poly_warn_if() -> std::nullptr_t {
1085  return {};
1086 }
1087 template <>
1088 [[deprecated(
1089  "make_poly_obj<T, D, Capacity>(): Specifying capacity with this "
1090  "API is error-prone, consider "
1091  "using a type alias instead to avoid repetition.")]] constexpr inline auto
1092 poly_warn_if<true>() -> std::nullptr_t {
1093  return {};
1094 }
1095 
1100 template <typename T, typename D = T, std::size_t Capacity = sizeof(D),
1101  typename Traits = poly_obj_traits<T>, typename... Args>
1103  Args&&... args,
1104  std::nullptr_t = poly_warn_if<(Capacity != sizeof(D)
1105  and Capacity > Traits::default_capacity)>())
1106  -> poly_obj<T, std::max(Capacity, Traits::default_capacity), Traits> {
1107  return poly_obj<T, std::max(Capacity, Traits::default_capacity),
1108  Traits>::template make<D>(std::forward<Args>(args)...);
1109 }
1110 
1111 } // namespace kblib
1112 
1113 #endif // POLY_OBJ_H
Inline polymorphic object. Generally mimics the interfaces of std::optional and std::variant.
Definition: poly_obj.h:481
auto get() const &noexcept -> const Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:819
auto operator->*(member_type(Obj::*member)(Args...) const &&) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1044
auto operator*() &noexcept -> Obj &
Returns a reference to the contained object.
Definition: poly_obj.h:754
const enable_if_t< not std::is_member_function_pointer< member_type Obj::* >::value, member_type > & operator->*(member_type Obj::*member) const &noexcept
Access a member variable using a pointer to member.
Definition: poly_obj.h:894
auto operator->*(member_type(Obj::*member)(Args...) const &) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:984
constexpr poly_obj(fakestd::in_place_t, Args &&... args) noexcept(std::is_nothrow_constructible< Obj, Args &&... >::value)
Constructs the contained object in-place without copying or moving.
Definition: poly_obj.h:543
auto operator*() &&noexcept(Traits::nothrow_movable) -> Obj &&
Returns a reference to the contained object.
Definition: poly_obj.h:778
auto operator->*(member_type(Obj::*member)(Args...)) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:924
auto operator->*(member_type(Obj::*member)(Args...) const &) const &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:996
auto get() &noexcept -> Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:809
auto operator->*(member_type(Obj::*member)(Args...) &) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:972
auto operator=(poly_obj &&other) &noexcept(Traits::nothrow_movable) -> poly_obj &
Destroys the contained object, if any, and then moves from other as in the move constructor.
Definition: poly_obj.h:693
static auto make(Args &&... args) noexcept(std::is_nothrow_constructible< U, Args &&... >::value) -> poly_obj
Constructs a poly_obj containing an object of derived type.
Definition: poly_obj.h:575
constexpr poly_obj(Obj &&obj) noexcept(Traits::nothrow_movable)
Move-constructs the contained object from obj.
Definition: poly_obj.h:531
enable_if_t< not std::is_member_function_pointer< member_type Obj::* >::value, member_type > & operator->*(member_type Obj::*member) &noexcept
Access a member variable using a pointer to member.
Definition: poly_obj.h:883
auto operator*() const &&noexcept(Traits::nothrow_movable) -> const Obj &&
Returns a reference to the contained object.
Definition: poly_obj.h:795
auto operator()(Args &&... args) const noexcept(is_nothrow_invocable< const Obj &, Args &&... >::value) -> fakestd::invoke_result_t< const Obj &, Args &&... >
Invokes the contained function object, if Obj is a callable type.
Definition: poly_obj.h:871
enable_if_t< not std::is_member_function_pointer< member_type Obj::* >::value, member_type > && operator->*(member_type Obj::*member) &&noexcept
Access a member variable using a pointer to member.
Definition: poly_obj.h:904
constexpr poly_obj(poly_obj &&other) noexcept(Traits::nothrow_movable)
Moves the contained object of other into this. Note that the moved- from poly_obj is not cleared; ins...
Definition: poly_obj.h:653
constexpr poly_obj(const Obj &obj)
Copy-constructs the contained object from obj.
Definition: poly_obj.h:522
constexpr poly_obj(const poly_obj &other)
Constructs a copy of other.
Definition: poly_obj.h:638
auto operator->*(member_type(Obj::*member)(Args...) const &&) const &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1056
Traits traits_type
Definition: poly_obj.h:500
auto operator=(const poly_obj &other) &-> poly_obj &
Destroys the contained object, if any, and then copies other as in the copy constructor.
Definition: poly_obj.h:671
auto operator->*(member_type(Obj::*member)(Args...) const) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:936
static auto make_aggregate(Args &&... args) noexcept(std::is_nothrow_constructible< U, Args &&... >::value) -> poly_obj
Constructs a poly_obj containing an object of derived type.
Definition: poly_obj.h:607
auto operator->() const &noexcept -> const Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:840
auto make_poly_obj(Args &&... args, std::nullptr_t=poly_warn_if<(Capacity !=sizeof(D) and Capacity > Traits::default_capacity)>()) -> poly_obj< T, std::max(Capacity, Traits::default_capacity), Traits >
A convenience factory for making poly_objs.
Definition: poly_obj.h:1102
auto operator->*(member_type(Obj::*member)(Args...) const) const &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:948
auto operator()(Args &&... args) noexcept(is_nothrow_invocable< Obj &, Args &&... >::value) -> fakestd::invoke_result_t< Obj &, Args &&... >
Invokes the contained function object, if Obj is a callable type.
Definition: poly_obj.h:855
~poly_obj() noexcept
Definition: poly_obj.h:732
constexpr poly_obj()=default
The default constructor does not construct any contained object.
auto operator->*(member_type(Obj::*member)(Args...) &&) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1008
auto has_value() const &noexcept -> bool
Definition: poly_obj.h:712
auto operator->*(member_type(Obj::*member)(Args...) const) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:960
constexpr poly_obj(std::nullptr_t) noexcept
Explicitly do not construct an object.
Definition: poly_obj.h:513
auto operator*() const &noexcept -> const Obj &
Returns a reference to the contained object.
Definition: poly_obj.h:765
constexpr poly_obj(kblib::in_place_agg_t, Args &&... args) noexcept(std::is_nothrow_constructible< Obj, Args &&... >::value)
Constructs the contained object in-place without copying or moving.
Definition: poly_obj.h:557
auto operator->() &noexcept -> Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:830
auto operator->*(member_type(Obj::*member)(Args...) const &) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1020
const enable_if_t< not std::is_member_function_pointer< member_type Obj::* >::value, member_type > && operator->*(member_type Obj::*member) const &&noexcept
Access a member variable using a pointer to member.
Definition: poly_obj.h:915
auto operator->*(member_type(Obj::*member)(Args...)) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1032
auto clear() noexcept -> void
Empties the poly_obj, reverting to a default-constructed state.
Definition: poly_obj.h:724
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
constexpr auto make_ctype(bool copyable, bool movable, bool nothrow_movable) -> construct_type
Definition: poly_obj.h:86
constexpr construct_type construct_traits
Definition: poly_obj.h:177
constexpr auto movable(construct_type type) noexcept -> bool
Definition: poly_obj.h:76
constexpr auto copyable(construct_type type) noexcept -> bool
Definition: poly_obj.h:72
constexpr auto nothrow_movable(construct_type type) noexcept -> bool
Definition: poly_obj.h:80
auto make_ops_t() noexcept -> erased_construct< Traits >
Definition: poly_obj.h:220
typename invoke_result< F, ArgTypes... >::type invoke_result_t
Definition: fakestd.h:171
typename make_void< Ts... >::type void_t
Definition: fakestd.h:178
constexpr struct kblib::nums::max_t max
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
construct_type
Definition: poly_obj.h:40
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
constexpr auto poly_warn_if() -> std::nullptr_t
Definition: poly_obj.h:1084
constexpr auto poly_warn_if< true >() -> std::nullptr_t
Definition: poly_obj.h:1092
constexpr auto operator|(construct_type l, construct_type r) noexcept -> construct_type
Definition: poly_obj.h:48
T alias
A simple identity alias for simplifying some compound type declarations, such as function pointers.
Definition: traits.h:155
auto get(punner< Types... > &p) noexcept -> decltype(auto)
Definition: bits.h:730
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail::do_invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(auto)
Definition: fakestd.h:130
typename void_if< b >::type void_if_t
Definition: fakestd.h:512
constexpr auto operator&(construct_type l, construct_type r) noexcept -> construct_type
Definition: poly_obj.h:54
constexpr auto copy(InputIt first, EndIt last, OutputIt out) -> OutputIt
Copies all elements of [first, last) to out. It also allows for a sentinel end iterator.
Definition: algorithm.h:1322
constexpr auto etoi(E e) -> auto
Definition: convert.h:244
constexpr auto operator*(construct_type l, bool r) noexcept -> construct_type
Definition: poly_obj.h:60
auto noop(void *, const T *) -> T *
Does nothing; matches the copy construction signature.
Definition: poly_obj.h:247
Definition: bits.h:714
The primary template has to exist, but not be constructible, in order to be compatible with std::hash...
Definition: hash.h:312
Implements copy construction using a virtual clone method. This type is provided mostly as an example...
Definition: poly_obj.h:291
clone_copy()=default
Does nothing.
auto copy(void *dest, const Obj *from) -> Obj *
Invokes the clone method to copy the object.
Definition: poly_obj.h:299
clone_copy(T *)
Does nothing.
Definition: poly_obj.h:296
auto copy(void *dest, const Obj *from) -> Obj *=delete
Implements type erasure for copy construction.
Definition: poly_obj.h:257
auto copy(void *dest, const Obj *from) -> Obj *
Copies an object of previously-established type.
Definition: poly_obj.h:275
default_copy() noexcept=default
Constructs an object which does nothing.
Uses the class's virtual destructor.
Definition: poly_obj.h:350
auto destroy(Obj *obj) -> void
Definition: poly_obj.h:355
default_destroy() noexcept=default
auto move(void *dest, Obj *from) noexcept(nothrow) -> Obj *=delete
auto move(void *dest, const Obj *from) noexcept(nothrow) -> Obj *
Definition: poly_obj.h:341
Implements type erasure for move construction.
Definition: poly_obj.h:305
auto move(void *dest, Obj *from) noexcept(nothrow) -> Obj *
Moves an object of previously-established type.
Definition: poly_obj.h:324
default_move() noexcept=default
Constructs an object which does nothing.
auto operator=(const construct_conditional &) -> construct_conditional &=default
auto operator=(construct_conditional &&) -> construct_conditional &=default
auto operator=(construct_conditional &&) -> construct_conditional &=default
auto operator=(const construct_conditional &) -> construct_conditional &=default
A metafunction for logical implication. That is, if A, then B. If not A, B is unimportant.
Definition: logic.h:45
poly_obj_traits is a traits class template which abstracts the allowed operations on a polymorphic ty...
Definition: poly_obj.h:374
Definition: logic.cpp:15
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:81
Provides utilities for working with std::variant more expressively and more efficiently.