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
38namespace KBLIB_NS {
39
40enum 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};
50 return static_cast<construct_type>(etoi(l) | etoi(r));
51}
52
55 return static_cast<construct_type>(etoi(l) & etoi(r));
56}
57
59 bool r) noexcept -> construct_type {
60 return r ? l : construct_type::none;
61}
62
68namespace detail_poly {
69
70 KBLIB_NODISCARD constexpr auto copyable(construct_type type) noexcept
71 -> bool {
72 return (type & construct_type::copy_only) != construct_type::none;
73 }
74 KBLIB_NODISCARD constexpr auto movable(construct_type type) noexcept
75 -> bool {
76 return (type & construct_type::move) != construct_type::none;
77 }
78 KBLIB_NODISCARD constexpr auto nothrow_movable(construct_type type) noexcept
79 -> bool {
80 return (type & construct_type::move) != construct_type::none
81 and (type & construct_type::throw_move) == construct_type::none;
82 }
83
85 bool copyable, bool movable, bool nothrow_movable) -> construct_type {
86 if (copyable) {
87 if (not movable) {
88 return construct_type::copy_only;
89 } else if (nothrow_movable) {
90 return construct_type::both;
91 } else {
92 return construct_type::both_throw;
93 }
94 } else if (movable) {
95 return construct_type::move;
96 } else {
97 return construct_type::none;
98 }
99 }
100
101 template <construct_type traits>
103
104 template <>
106 construct_conditional() noexcept = default;
109
110 auto operator=(const construct_conditional&)
111 -> construct_conditional& = default;
112 auto operator=(construct_conditional&&)
113 -> construct_conditional& = default;
115 };
116
117 template <>
119 construct_conditional() noexcept = default;
122
123 auto operator=(const construct_conditional&)
124 -> construct_conditional& = default;
125 auto operator=(construct_conditional&&)
126 -> construct_conditional& = default;
128 };
129
130 template <>
132 construct_conditional() noexcept = default;
135
136 auto operator=(const construct_conditional&)
137 -> construct_conditional& = default;
138 auto operator=(construct_conditional&&)
139 -> construct_conditional& = default;
141 };
142
143 template <>
145
146 template <>
148 construct_conditional() noexcept = default;
151
153 -> construct_conditional& = default;
155 -> construct_conditional& = default;
157 };
158
159 template <>
161 construct_conditional() noexcept = default;
164
166 -> construct_conditional& = default;
168 -> construct_conditional& = default;
170 };
171
172 template <typename T>
174 = construct_type::copy_only * std::is_copy_constructible<T>::value
175 | construct_type::move * std::is_move_constructible<T>::value
176 | construct_type::throw_move
179
180 template <typename T, typename hash = void>
181 struct erased_hash_t {};
182
183 template <typename T>
184 struct erased_hash_t<T, void_t<fakestd::invoke_result_t<std::hash<T>, T>>> {
185 static auto default_hash(void* obj) -> std::size_t {
186 return std::hash<T>()(*static_cast<const T*>(obj));
187 }
188
189 alias<std::size_t (*)(void*)> hash = &default_hash;
190 };
191
192 template <typename T, typename hash = void>
194
195 template <typename T>
197 T, void_t<fakestd::invoke_result_t<std::hash<T>, T>>> {
198 static auto default_hash(void* obj) -> std::size_t {
199 return FNV_hash<T>{}(*static_cast<const T*>(obj));
200 }
201
202 alias<std::size_t (*)(void*)> hash = &default_hash;
203 };
204
205 template <typename Traits>
207 : Traits::copy_t
208 , Traits::move_t
209 , Traits::destroy_t {
211 using Traits::move_t::move;
212
213 using Traits::destroy_t::destroy;
214 };
215
216 template <typename T, typename Traits>
217 KBLIB_NODISCARD auto make_ops_t() noexcept -> erased_construct<Traits> {
218 static_assert(implies<Traits::copyable,
220 "T must be copy constructible if Traits is.");
221 static_assert(
224 "T must be nothrow move constructible if Traits is.");
225 static_assert(
227 "T must be move constructible if Traits is.");
228 return {{typename Traits::copy_t{static_cast<T*>(nullptr)}},
229 {typename Traits::move_t{static_cast<T*>(nullptr)}},
230 {typename Traits::destroy_t{static_cast<T*>(nullptr)}}};
231 }
232
233 template <typename T, typename = void>
235 : std::integral_constant<std::size_t, sizeof(T)> {};
236 template <typename T>
237 struct extract_derived_size<T, void_if_t<(T::max_derived_size > sizeof(T))>>
238 : std::integral_constant<std::size_t, T::max_derived_size> {};
239
240} // namespace detail_poly
241
243template <typename T>
244inline auto noop(void*, const T*) -> T* {
245 return nullptr;
246}
248template <typename T, bool nothrow>
249inline auto noop(void*, T*) noexcept(nothrow) -> T* {
250 return nullptr;
251}
253template <typename Obj, bool copyable>
255 private:
256 template <typename T>
257 static auto do_copy(void* dest, const Obj* from) -> Obj* {
258 return static_cast<Obj*>(new (dest) T(*static_cast<const T*>(from)));
259 }
260
261 auto (*p_copy)(void* dest, const Obj* from) -> Obj* = &noop<Obj>;
262
263 public:
265 default_copy() noexcept = default;
267 template <typename T>
268 explicit default_copy(T*) noexcept
269 : p_copy(&do_copy<T>) {}
270
272 KBLIB_NODISCARD auto copy(void* dest, const Obj* from) -> Obj* {
273 return p_copy(dest, from);
274 }
275};
276template <typename Obj>
277struct default_copy<Obj, false> {
278 default_copy() noexcept = default;
279 template <typename T>
280 explicit default_copy(T*) noexcept {}
281 auto copy(void* dest, const Obj* from) -> Obj* = delete;
282};
287template <typename Obj, auto (Obj::* clone)(void*) const->Obj*>
290 clone_copy() = default;
292 template <typename T>
294
296 KBLIB_NODISCARD auto copy(void* dest, const Obj* from) -> Obj* {
297 return (from->*clone)(dest);
298 }
299};
301template <typename Obj, bool movable, bool nothrow, bool copyable>
303 private:
304 template <typename T>
305 static auto do_move(void* dest, Obj* from) noexcept(nothrow) -> Obj* {
306 return static_cast<Obj*>(new (dest) T(std::move(*static_cast<T*>(from))));
307 }
308 // noexcept isn't working here on clang
309 auto (*p_move)(void* dest,
310 Obj* from) noexcept(false) -> Obj* = &noop<Obj, nothrow>;
311
312 public:
314 default_move() noexcept = default;
316 template <typename T>
317 explicit default_move(T*) noexcept
318 : p_move(&do_move<T>) {}
319
321 KBLIB_NODISCARD auto move(void* dest, Obj* from) noexcept(nothrow) -> Obj* {
322 return p_move(dest, from);
323 }
324};
325template <typename Obj, bool nothrow>
326struct default_move<Obj, false, nothrow, false> {
327 default_move() noexcept = default;
328 template <typename T>
329 explicit default_move(T*) noexcept {}
330 auto move(void* dest, Obj* from) noexcept(nothrow) -> Obj* = delete;
331};
332// fallback on copy
333template <typename Obj, bool nothrow>
334struct default_move<Obj, false, nothrow, true>
335 : private default_copy<Obj, true> {
336 using default_copy<Obj, true>::default_copy;
337
338 KBLIB_NODISCARD auto move(void* dest,
339 const Obj* from) noexcept(nothrow) -> Obj* {
340 return this->copy(dest, from);
341 }
342};
346template <typename Obj>
348 default_destroy() noexcept = default;
349 template <typename T>
350 explicit default_destroy(T*) noexcept {}
351
352 auto destroy(Obj* obj) -> void { obj->~Obj(); }
354 "Obj must have a virtual destructor");
355};
356
357// TODO(killerbee13): Distinguish between pointers to T and to most-derived
358// object
359
369template <typename Obj,
370 construct_type CType = detail_poly::construct_traits<Obj>>
372
379 constexpr static std::size_t default_capacity
381
385 constexpr static std::size_t alignment
386 = std::max(alignof(Obj), alignof(std::max_align_t));
387
391 constexpr static bool copyable = detail_poly::copyable(CType);
392
396 constexpr static bool movable = detail_poly::movable(CType);
400 constexpr static bool nothrow_movable = detail_poly::nothrow_movable(CType);
401
415
430
445 static_assert(std::is_empty<destroy_t>::value, "");
446};
447
448template <typename Obj>
450template <typename Obj>
452
473template <typename Obj, std::size_t Capacity = 0,
474 typename Traits = poly_obj_traits<Obj>>
476 : private detail_poly::construct_conditional<detail_poly::make_ctype(
477 Traits::copyable, Traits::movable, Traits::nothrow_movable)>
478 , private detail_poly::erased_construct<Traits> {
479 private:
483
484 public:
488 static constexpr std::size_t capacity
489 = Capacity > 0 ? Capacity : Traits::default_capacity;
490
491 static_assert(capacity >= sizeof(Obj),
492 "Capacity must be large enough for the object type.");
493 static_assert(not std::is_array<Obj>::value,
494 "poly_obj of array type is disallowed.");
495
496 using base_type = Obj;
497 using traits_type = Traits;
498
503
506 constexpr poly_obj() = default;
510 constexpr poly_obj(std::nullptr_t) noexcept
511 : poly_obj() {}
519 constexpr poly_obj(const Obj& obj)
520 : ptr(new(data) Obj(obj)) {}
528 constexpr poly_obj(Obj&& obj) noexcept(Traits::nothrow_movable)
529 : ptr(new(data) Obj(std::move(obj))) {}
530
537 template <typename... Args,
538 typename std::enable_if_t<
539 std::is_constructible<Obj, Args...>::value, int>
540 = 0>
541 constexpr explicit poly_obj(fakestd::in_place_t, Args&&... args) noexcept(
542 std::is_nothrow_constructible<Obj, Args&&...>::value)
543 : ops_t(detail_poly::make_ops_t<Obj, Traits>())
544 , ptr(new(data) Obj(std::forward<Args>(args)...)) {}
545
552 template <typename... Args,
553 typename std::enable_if_t<
554 std::is_constructible<Obj, Args...>::value, int>
555 = 0>
556 constexpr explicit poly_obj(kblib::in_place_agg_t, Args&&... args) noexcept(
557 std::is_nothrow_constructible<Obj, Args&&...>::value)
558 : ops_t(detail_poly::make_ops_t<Obj, Traits>())
559 , ptr(new(data) Obj{std::forward<Args>(args)...}) {}
560
561 private:
562 template <typename U>
563 constexpr static void assert_emplaceable() {
564 static_assert(sizeof(U) <= capacity,
565 "U must fit inside of the inline capacity.");
566 static_assert(alignof(U) <= Traits::alignment,
567 "U must be no more aligned than Traits::alignment");
570 "Obj must be an accessible base of U.");
571 static_assert(
572 implies<Traits::copyable,
574 "U must be copy constructible if Traits::copyable is true.");
575 static_assert(
577 "U must be move constructible if Traits::movable is true.");
578 }
579
580 public:
581 template <typename U, bool aggregate = false>
582 struct tag {};
583
584 template <typename U, typename... Args>
585 poly_obj(tag<U>, Args&&... args) noexcept(
586 std::is_nothrow_constructible<U, Args&&...>::value)
587 : ops_t(detail_poly::make_ops_t<U, Traits>())
588 , ptr(new(data) U(std::forward<Args>(args)...)) {
589 assert_emplaceable<U>();
590 }
591
592 template <typename U, typename... Args>
593 poly_obj(tag<U, true>, Args&&... args) noexcept(
594 std::is_nothrow_constructible<U, Args&&...>::value)
595 : ops_t(detail_poly::make_ops_t<U, Traits>())
596 , ptr(new(data) U{std::forward<Args>(args)...}) {
597 assert_emplaceable<U>();
598 }
599
612 template <typename U, typename... Args>
613 KBLIB_NODISCARD static auto make(Args&&... args) noexcept(
614 std::is_nothrow_constructible<U, Args&&...>::value) -> poly_obj {
615 assert_emplaceable<U>();
616 return {tag<U>{}, std::forward<Args>(args)...};
617 }
618
631 template <typename U, typename... Args>
632 KBLIB_NODISCARD static auto make_aggregate(Args&&... args) noexcept(
633 std::is_nothrow_constructible<U, Args&&...>::value) -> poly_obj {
634 assert_emplaceable<U>();
635 return {tag<U, true>{}, std::forward<Args>(args)...};
636 }
638
639 template <typename U, typename... Args>
640 constexpr auto emplace(Args&&... args) noexcept(
641 std::is_nothrow_constructible<U, Args&&...>::value) -> U* {
642 assert_emplaceable<U>();
643 clear();
644
645 static_cast<ops_t&>(*this) = detail_poly::make_ops_t<U, Traits>();
646 auto r = new (data) U(std::forward<Args>(args)...);
647 ptr = r;
648 return r;
649 }
650
655
662 constexpr poly_obj(const poly_obj& other)
663 : disabler(other)
664 , ops_t(other) {
665 if (other.ptr) {
666 ptr = this->copy(data, other.ptr);
667 }
668 }
677 constexpr poly_obj(poly_obj&& other) noexcept(Traits::nothrow_movable)
678 : disabler(std::move(other))
679 , ops_t(std::move(other)) {
680 if (other.ptr) {
681 ptr = this->move(data, other.ptr);
682 }
683 }
684
695 auto operator=(const poly_obj& other) & -> poly_obj& {
696 if (this == &other) {
697 return *this;
698 }
699 clear();
700 static_cast<ops_t&>(*this) = other;
701 if (other.ptr) {
702 ptr = this->copy(data, other.ptr);
703 }
704 return *this;
705 }
706
718 -> poly_obj& {
719 if (this == &other) {
720 return *this;
721 }
722 clear();
723 static_cast<ops_t&>(*this) = other;
724 if (other.ptr) {
725 ptr = this->move(data, other.ptr);
726 }
727 return *this;
728 }
730
736 KBLIB_NODISCARD auto has_value() const& noexcept -> bool { return ptr; }
737
738 explicit operator bool() const& noexcept { return has_value(); }
740
745
748 auto clear() noexcept -> void {
749 if (ptr) {
750 this->destroy(ptr);
751 ptr = nullptr;
752 }
753 static_cast<ops_t&>(*this) = {};
754 }
755
756 ~poly_obj() noexcept {
757 if (ptr) {
758 this->destroy(ptr);
759 }
760 }
762
768
778 KBLIB_NODISCARD auto operator*() & noexcept -> Obj& { return *get(); }
789 KBLIB_NODISCARD auto operator*() const& noexcept -> const Obj& {
790 return *get();
791 }
803 -> Obj&& {
804 return std::move(*get());
805 }
819 KBLIB_NODISCARD auto operator*() const&& noexcept(Traits::nothrow_movable)
820 -> const Obj&& {
821 return std::move(*get());
822 }
823
833 KBLIB_NODISCARD auto get() & noexcept -> Obj* { return ptr; }
843 KBLIB_NODISCARD auto get() const& noexcept -> const Obj* { return ptr; }
844
854 KBLIB_NODISCARD auto operator->() & noexcept -> Obj* { return ptr; }
864 KBLIB_NODISCARD auto operator->() const& noexcept -> const Obj* {
865 return ptr;
866 }
867
878 template <typename... Args>
879 auto operator()(Args&&... args) noexcept(
880 is_nothrow_invocable<Obj&, Args&&...>::value)
882 return kblib::invoke(*get(), std::forward<Args>(args)...);
883 }
894 template <typename... Args>
895 auto operator()(Args&&... args) const
896 noexcept(is_nothrow_invocable<const Obj&, Args&&...>::value)
898 return kblib::invoke(*get(), std::forward<Args>(args)...);
899 }
900
904 template <typename member_type>
906 member_type>&
907 operator->*(member_type Obj::* member) & noexcept {
908 return get()->*member;
909 }
910
914 template <typename member_type>
915 const enable_if_t<
917 member_type>&
918 operator->*(member_type Obj::* member) const& noexcept {
919 return get()->*member;
920 }
921
925 template <typename member_type>
927 member_type>&&
928 operator->*(member_type Obj::* member) && noexcept {
929 return std::move(get()->*member);
930 }
931
935 template <typename member_type>
936 const enable_if_t<
938 member_type>&&
939 operator->*(member_type Obj::* member) const&& noexcept {
940 return std::move(get()->*member);
941 }
942
947 template <typename member_type, typename... Args>
949 member_type (Obj::* member)(Args...)) & 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>
972 KBLIB_NODISCARD auto operator->*(member_type (Obj::* member)(Args...)
973 const) const& 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>
997 member_type (Obj::* member)(Args...) &) & 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 const&) & noexcept {
1010 return [member, value = get()](Args... args) -> decltype(auto) {
1011 return (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&) 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 (std::move(*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 (value->*member)(std::forward<Args>(args)...);
1048 };
1049 }
1050
1055 template <typename member_type, typename... Args>
1057 member_type (Obj::* member)(Args...)) && noexcept {
1058 return [member, value = get()](Args... args) -> decltype(auto) {
1059 return (value->*member)(std::forward<Args>(args)...);
1060 };
1061 }
1062
1067 template <typename member_type, typename... Args>
1068 KBLIB_NODISCARD auto operator->*(member_type (Obj::* member)(Args...)
1069 const&&) && noexcept {
1070 return [member, value = get()](Args... args) -> decltype(auto) {
1071 return (std::move(*value).*member)(std::forward<Args>(args)...);
1072 };
1073 }
1074
1079 template <typename member_type, typename... Args>
1080 KBLIB_NODISCARD auto operator->*(member_type (Obj::* member)(Args...)
1081 const&&) const&& noexcept {
1082 return [member, value = get()](Args... args) -> decltype(auto) {
1083 return (std::move(*value).*member)(std::forward<Args>(args)...);
1084 };
1085 }
1086
1087 private:
1088 alignas(Traits::alignment) byte data[capacity]{};
1089 Obj* ptr{};
1090};
1091
1092template <bool warn>
1093constexpr auto poly_warn_if() -> std::nullptr_t {
1094 return {};
1095}
1096template <>
1097[[deprecated(
1098 "make_poly_obj<T, D, Capacity>(): Specifying capacity with this "
1099 "API is error-prone, consider "
1100 "using a type alias instead to avoid repetition.")]] constexpr inline auto
1101poly_warn_if<true>() -> std::nullptr_t {
1102 return {};
1103}
1104
1109template <typename T, typename D = T, std::size_t Capacity = sizeof(D),
1110 typename Traits = poly_obj_traits<T>, typename... Args>
1112 Args&&... args,
1113 std::nullptr_t = poly_warn_if<(Capacity != sizeof(D)
1114 and Capacity > Traits::default_capacity)>())
1115 -> poly_obj<T, std::max(Capacity, Traits::default_capacity), Traits> {
1116 return poly_obj<T, std::max(Capacity, Traits::default_capacity),
1117 Traits>::template make<D>(std::forward<Args>(args)...);
1118}
1119
1120} // namespace KBLIB_NS
1121
1122#endif // POLY_OBJ_H
Inline polymorphic object. Generally mimics the interfaces of std::optional and std::variant.
Definition: poly_obj.h:478
auto get() const &noexcept -> const Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:843
auto operator->*(member_type(Obj::*member)(Args...) const &&) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1068
auto operator*() &noexcept -> Obj &
Returns a reference to the contained object.
Definition: poly_obj.h:778
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:907
auto operator->*(member_type(Obj::*member)(Args...) const &) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1008
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:541
auto operator*() &&noexcept(Traits::nothrow_movable) -> Obj &&
Returns a reference to the contained object.
Definition: poly_obj.h:802
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:928
auto operator->*(member_type(Obj::*member)(Args...)) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:948
auto operator->*(member_type(Obj::*member)(Args...) const &) const &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1020
auto get() &noexcept -> Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:833
auto operator->*(member_type(Obj::*member)(Args...) &) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:996
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:717
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:613
constexpr poly_obj(Obj &&obj) noexcept(Traits::nothrow_movable)
Move-constructs the contained object from obj.
Definition: poly_obj.h:528
auto operator*() const &&noexcept(Traits::nothrow_movable) -> const Obj &&
Returns a reference to the contained object.
Definition: poly_obj.h:819
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:895
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:677
constexpr poly_obj(const Obj &obj)
Copy-constructs the contained object from obj.
Definition: poly_obj.h:519
constexpr auto emplace(Args &&... args) noexcept(std::is_nothrow_constructible< U, Args &&... >::value) -> U *
Definition: poly_obj.h:640
constexpr poly_obj(const poly_obj &other)
Constructs a copy of other.
Definition: poly_obj.h:662
auto operator->*(member_type(Obj::*member)(Args...) const &&) const &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1080
poly_obj(tag< U >, Args &&... args) noexcept(std::is_nothrow_constructible< U, Args &&... >::value)
Definition: poly_obj.h:585
Traits traits_type
Definition: poly_obj.h:497
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:695
auto operator->*(member_type(Obj::*member)(Args...) const) &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:960
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:632
auto operator->() const &noexcept -> const Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:864
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:1111
auto operator->*(member_type(Obj::*member)(Args...) const) const &noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:972
poly_obj(tag< U, true >, Args &&... args) noexcept(std::is_nothrow_constructible< U, Args &&... >::value)
Definition: poly_obj.h:593
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:879
~poly_obj() noexcept
Definition: poly_obj.h:756
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:1032
auto has_value() const &noexcept -> bool
Definition: poly_obj.h:736
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:939
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(std::nullptr_t) noexcept
Explicitly do not construct an object.
Definition: poly_obj.h:510
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:918
auto operator*() const &noexcept -> const Obj &
Returns a reference to the contained object.
Definition: poly_obj.h:789
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:556
auto operator->() &noexcept -> Obj *
Returns a pointer to the contained object.
Definition: poly_obj.h:854
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->*(member_type(Obj::*member)(Args...)) &&noexcept
Call a member function using a pointer to member.
Definition: poly_obj.h:1056
auto clear() noexcept -> void
Empties the poly_obj, reverting to a default-constructed state.
Definition: poly_obj.h:748
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4001
constexpr auto make_ctype(bool copyable, bool movable, bool nothrow_movable) -> construct_type
Definition: poly_obj.h:84
constexpr construct_type construct_traits
Definition: poly_obj.h:174
constexpr auto movable(construct_type type) noexcept -> bool
Definition: poly_obj.h:74
constexpr auto copyable(construct_type type) noexcept -> bool
Definition: poly_obj.h:70
constexpr auto nothrow_movable(construct_type type) noexcept -> bool
Definition: poly_obj.h:78
auto make_ops_t() noexcept -> erased_construct< Traits >
Definition: poly_obj.h:217
typename invoke_result< F, ArgTypes... >::type invoke_result_t
Definition: fakestd.h:185
typename make_void< Ts... >::type void_t
Definition: fakestd.h:192
constexpr struct kblib::nums::max_t max
auto noop(void *, T *) noexcept(nothrow) -> T *
Does nothing; matches the move construction signature.
Definition: poly_obj.h:249
construct_type
Definition: poly_obj.h:40
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:62
constexpr auto poly_warn_if() -> std::nullptr_t
Definition: poly_obj.h:1093
constexpr auto poly_warn_if< true >() -> std::nullptr_t
Definition: poly_obj.h:1101
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:735
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:144
typename void_if< b >::type void_if_t
Definition: fakestd.h:530
constexpr auto operator&(construct_type l, construct_type r) noexcept -> construct_type
Definition: poly_obj.h:53
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:279
constexpr auto operator*(construct_type l, bool r) noexcept -> construct_type
Definition: poly_obj.h:58
The primary template has to exist, but not be constructible, in order to be compatible with std::hash...
Definition: hash.h:334
Implements copy construction using a virtual clone method. This type is provided mostly as an example...
Definition: poly_obj.h:288
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:296
clone_copy(T *)
Does nothing.
Definition: poly_obj.h:293
auto copy(void *dest, const Obj *from) -> Obj *=delete
Implements type erasure for copy construction.
Definition: poly_obj.h:254
auto copy(void *dest, const Obj *from) -> Obj *
Copies an object of previously-established type.
Definition: poly_obj.h:272
default_copy() noexcept=default
Constructs an object which does nothing.
Uses the class's virtual destructor.
Definition: poly_obj.h:347
auto destroy(Obj *obj) -> void
Definition: poly_obj.h:352
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:338
Implements type erasure for move construction.
Definition: poly_obj.h:302
auto move(void *dest, Obj *from) noexcept(nothrow) -> Obj *
Moves an object of previously-established type.
Definition: poly_obj.h:321
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:371
#define KBLIB_NS
Definition: tdecl.h:130
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:146
Provides utilities for working with std::variant more expressively and more efficiently.