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};
49 construct_type r) noexcept
51 return static_cast<construct_type>(etoi(l) | etoi(r));
52}
53
55 construct_type r) noexcept
57 return static_cast<construct_type>(etoi(l) & etoi(r));
58}
59
60KBLIB_NODISCARD constexpr auto operator*(construct_type l, bool r) noexcept
62 return r ? l : construct_type::none;
63}
64
70namespace detail_poly {
71
72 KBLIB_NODISCARD constexpr auto copyable(construct_type type) noexcept
73 -> bool {
74 return (type & construct_type::copy_only) != construct_type::none;
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 {
82 return (type & construct_type::move) != construct_type::none
83 and (type & construct_type::throw_move) == construct_type::none;
84 }
85
86 KBLIB_NODISCARD constexpr auto make_ctype(bool copyable, bool movable,
87 bool nothrow_movable)
89 if (copyable) {
90 if (not movable) {
91 return construct_type::copy_only;
92 } else if (nothrow_movable) {
93 return construct_type::both;
94 } else {
95 return construct_type::both_throw;
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;
118 };
119
120 template <>
122 construct_conditional() noexcept = default;
125
126 auto operator=(const construct_conditional&)
127 -> construct_conditional& = default;
128 auto operator=(construct_conditional&&)
129 -> construct_conditional& = default;
131 };
132
133 template <>
135 construct_conditional() noexcept = default;
138
139 auto operator=(const construct_conditional&)
140 -> construct_conditional& = default;
141 auto operator=(construct_conditional&&)
142 -> construct_conditional& = default;
144 };
145
146 template <>
148
149 template <>
151 construct_conditional() noexcept = default;
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
179 | construct_type::throw_move*(
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 {
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(
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
246template <typename T>
247inline auto noop(void*, const T*) -> T* {
248 return nullptr;
249}
251template <typename T, bool nothrow>
252inline auto noop(void*, T*) noexcept(nothrow) -> T* {
253 return nullptr;
254}
256template <typename Obj, bool copyable>
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};
279template <typename Obj>
280struct 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};
290template <typename Obj, auto (Obj::*clone)(void*) const->Obj*>
293 clone_copy() = default;
295 template <typename T>
297
299 KBLIB_NODISCARD auto copy(void* dest, const Obj* from) -> Obj* {
300 return (from->*clone)(dest);
301 }
302};
304template <typename Obj, bool movable, bool nothrow, bool copyable>
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};
328template <typename Obj, bool nothrow>
329struct 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
336template <typename Obj, bool nothrow>
337struct default_move<Obj, false, nothrow, true>
338 : private default_copy<Obj, true> {
339 using default_copy<Obj, true>::default_copy;
340
341 KBLIB_NODISCARD auto move(void* dest, const Obj* from) noexcept(nothrow)
342 -> Obj* {
343 return this->copy(dest, from);
344 }
345};
349template <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
372template <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
451template <typename Obj>
453template <typename Obj>
455
476template <typename Obj, std::size_t Capacity = 0,
477 typename Traits = poly_obj_traits<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(
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(
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
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(
856 is_nothrow_invocable<Obj&, Args&&...>::value)
858 return kblib::invoke(*get(), std::forward<Args>(args)...);
859 }
870 template <typename... Args>
871 auto operator()(Args&&... args) const
872 noexcept(is_nothrow_invocable<const Obj&, Args&&...>::value)
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
1083template <bool warn>
1084constexpr auto poly_warn_if() -> std::nullptr_t {
1085 return {};
1086}
1087template <>
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
1092poly_warn_if<true>() -> std::nullptr_t {
1093 return {};
1094}
1095
1100template <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_NS
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
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->*(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
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
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
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
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
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...) 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
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*() 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
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:172
typename make_void< Ts... >::type void_t
Definition: fakestd.h:179
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:252
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:737
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:131
typename void_if< b >::type void_if_t
Definition: fakestd.h:513
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
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: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_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129
Provides utilities for working with std::variant more expressively and more efficiently.