35std::vector<barks> bark_log;
38 good_base() =
default;
39 virtual ~good_base() noexcept { bark_log.push_back(dgood_base); }
41 virtual auto bark() const ->
void { bark_log.push_back(vgood_base); }
43struct good_derived : good_base {
44 ~good_derived() noexcept
override { bark_log.push_back(dgood_derived); }
46 auto bark() const ->
void override { bark_log.push_back(vgood_derived); }
49struct bad_nocopy : good_base {
50 bad_nocopy(
const bad_nocopy&) =
delete;
54 virtual auto bark() const ->
void { bark_log.push_back(vbad_base1); }
56 ~bad_base1() noexcept { bark_log.push_back(dbad_base1); }
58struct bad_derived1 : bad_base1 {
59 auto bark() const ->
void override { bark_log.push_back(vbad_derived1); }
60 KBLIB_UNUSED ~bad_derived1() noexcept { bark_log.push_back(dbad_derived1); }
64 bad_base2() =
default;
65 virtual ~bad_base2() noexcept { bark_log.push_back(dbad_base2); }
66 virtual auto bark() const ->
void { bark_log.push_back(vbad_base2); }
68struct bad_derived2 :
protected bad_base2 {
69 auto bark() const ->
void override { bark_log.push_back(vbad_derived2); }
70 ~bad_derived2() noexcept
override { bark_log.push_back(dbad_derived2); }
73 small_base() =
default;
74 virtual ~small_base() noexcept = default;
75 virtual auto bark() const ->
void { bark_log.push_back(vsmall_base); }
76 virtual auto id() const ->
int {
return 0; }
78struct big_derived : small_base {
83 x = kblib::FNVa_a<std::size_t>(
84 reinterpret_cast<const char(&)[sizeof(big_derived)]
>(*
this));
86 auto bark() const ->
void override { bark_log.push_back(vbig_derived); }
87 ~big_derived() noexcept override = default;
88 auto
id() const ->
int override {
return 1; }
92 not_copyable() =
default;
93 not_copyable(
const not_copyable&) =
delete;
94 KBLIB_UNUSED not_copyable(not_copyable&&) noexcept = default;
95 virtual ~not_copyable() = default;
98struct copyable_derived : not_copyable {
100 copyable_derived(
const copyable_derived&) {}
101 copyable_derived(copyable_derived&&) noexcept = default;
104struct copyable_base {
105 virtual ~copyable_base() =
default;
108struct noncopyable_derived : copyable_base {
110 noncopyable_derived(
const noncopyable_derived&) =
delete;
111 KBLIB_UNUSED noncopyable_derived(noncopyable_derived&&) =
default;
115 constexpr static std::size_t max_derived_size =
sizeof(big_derived);
116 virtual ~hinted_base() =
default;
119struct hinted_derived : hinted_base {
130 std::vector<barks> expected;
137 expected.push_back(vgood_base);
142 expected.push_back(dgood_derived);
143 expected.push_back(dgood_base);
148 expected.push_back(vgood_derived);
152 expected.push_back(dgood_base);
156 expected.push_back(vgood_derived);
160 expected.push_back(dgood_derived);
161 expected.push_back(dgood_base);
169 expected.push_back(dgood_derived);
170 expected.push_back(dgood_base);
174 SECTION(
"non-virtual destructor") {
181 std::vector<barks> expected;
188 expected.push_back(dbad_base2);
193 std::vector<barks> expected;
201 kblib::poly_obj<small_base,
sizeof(big_derived)> o7, o8{std::in_place};
203 expected.push_back(vsmall_base);
206 sizeof(big_derived)>::make<big_derived>();
209 expected.push_back(vbig_derived);
226 SECTION(
"non-copyable derived") {
232 auto o2 =
decltype(o1)::make<noncopyable_derived>();
236 auto r = [n = std::uint16_t{16127}]()
mutable {
239 return kblib::FNV32a({
reinterpret_cast<char*
>(&n),
sizeof(n)});
244 std::vector<obj> polyvec;
249 return obj::make<big_derived>();
252 return obj(std::in_place);
260 for (
const auto& o : polyvec) {
268 SECTION(
"free make function") {
271 auto o = kblib::make_poly_obj<small_base, big_derived>();
273 std::is_same_v<
decltype(o),
275 "make_poly_obj must return the correct type.");
279 == hinted_base::max_derived_size);
281 static_assert(
decltype(o)::capacity
282 ==
decltype(o)::base_type::max_derived_size);
283 o =
decltype(o)::make<hinted_derived>();
290 auto get_member() &
noexcept ->
int {
return member; }
291 auto cget_member() const& noexcept ->
int {
return member; }
292 auto rget_member() &&
noexcept ->
int {
return member; }
293 auto crget_member() const&& noexcept ->
int {
return member; }
295 auto get_member2() noexcept ->
int {
return member; }
296 auto cget_member2() const noexcept ->
int {
return member; }
298 virtual ~mem_ptr_test() =
default;
305 constexpr auto data_member = &mem_ptr_test::member;
306 REQUIRE(obj->*data_member == 42);
307 static_assert(std::is_same_v<
decltype(obj->*data_member),
int&>);
308 static_assert(std::is_same_v<
decltype(std::as_const(obj)->*data_member),
311 std::is_same_v<
decltype(std::move(obj)->*data_member),
int&&>);
313 std::is_same_v<
decltype(std::move(std::as_const(obj))->*data_member),
317 constexpr auto func_member = &mem_ptr_test::get_member;
318 constexpr auto cfunc_member = &mem_ptr_test::cget_member;
319 constexpr auto rfunc_member = &mem_ptr_test::rget_member;
320 constexpr auto crfunc_member = &mem_ptr_test::crget_member;
321 REQUIRE((obj->*func_member)() == 42);
322 static_assert(std::is_same_v<
decltype((obj->*func_member)()),
int>);
323 REQUIRE((obj->*cfunc_member)() == 42);
324 static_assert(std::is_same_v<
decltype((obj->*cfunc_member)()),
int>);
325 REQUIRE((std::as_const(obj)->*cfunc_member)() == 42);
327 std::is_same_v<
decltype((std::as_const(obj)->*cfunc_member)()),
int>);
328 REQUIRE((std::move(obj)->*rfunc_member)() == 42);
330 std::is_same_v<
decltype((std::move(obj)->*rfunc_member)()),
int>);
331 REQUIRE((std::move(obj)->*crfunc_member)() == 42);
333 std::is_same_v<
decltype((std::move(obj)->*crfunc_member)()),
int>);
334 REQUIRE((std::move(std::as_const(obj))->*crfunc_member)() == 42);
335 static_assert(std::is_same_v<
336 decltype((std::move(std::as_const(obj))->*crfunc_member)()),
339 constexpr auto func_member2 = &mem_ptr_test::get_member2;
340 constexpr auto cfunc_member2 = &mem_ptr_test::cget_member2;
342 REQUIRE((obj->*func_member2)() == 42);
343 static_assert(std::is_same_v<
decltype((obj->*func_member2)()),
int>);
344 REQUIRE((obj->*cfunc_member2)() == 42);
345 static_assert(std::is_same_v<
decltype((obj->*cfunc_member2)()),
int>);
346 REQUIRE((std::as_const(obj)->*cfunc_member2)() == 42);
348 std::is_same_v<
decltype((std::as_const(obj)->*cfunc_member2)()),
Inline polymorphic object. Generally mimics the interfaces of std::optional and std::variant.
auto has_value() const &noexcept -> bool
auto clear() noexcept -> void
Empties the poly_obj, reverting to a default-constructed state.
constexpr auto generate_n(OutputIt first, Size count, Generator g) noexcept(noexcept(*first++=g())) -> OutputIt
Like std::generate_n except that it is constexpr.
constexpr auto FNV32a(std::string_view s, std::uint32_t hval=fnv::fnv_offset< std::uint32_t >::value) noexcept -> std::uint32_t
A standard FNV32a hash function, for string_views.
Provides poly_obj, which enables polymorphism to be used without unnecessary per-object dynamic alloc...
poly_obj_traits is a traits class template which abstracts the allowed operations on a polymorphic ty...
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.