KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_ki_any.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20// Tests taken from GCC:
21// Copyright (C) 2014-2024 Free Software Foundation, Inc.
22//
23// This file is part of the GNU ISO C++ Library. This library is free
24// software; you can redistribute it and/or modify it under the
25// terms of the GNU General Public License as published by the
26// Free Software Foundation; either version 3, or (at your option)
27// any later version.
28
29// This library is distributed in the hope that it will be useful,
30// but WITHOUT ANY WARRANTY; without even the implied warranty of
31// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32// GNU General Public License for more details.
33
34// Under Section 7 of GPL version 3, you are granted additional
35// permissions described in the GCC Runtime Library Exception, version
36// 3.1, as published by the Free Software Foundation.
37
38// You should have received a copy of the GNU General Public License and
39// a copy of the GCC Runtime Library Exception along with this program.
40// If not, see <https://www.gnu.org/licenses/>.
41
42#include <boost/test/unit_test.hpp>
43
44#include <cstdint>
45#include <memory>
46#include <set>
47#include <utility>
48#include <type_traits>
49
50#include <ki_any.h>
51
52using ki::any;
53using ki::any_cast;
54
56// Exception hierarchy
59static_assert(std::is_base_of<std::bad_cast, ki::bad_any_cast>::value,
60 "ki::bad_any_cast must derive from std::bad_cast");
61
63// Type requirements
65
66static_assert(std::is_assignable<any&, int>::value);
67static_assert(!std::is_assignable<any&, std::unique_ptr<int>>::value);
68static_assert(std::is_constructible<any, int>::value);
69static_assert(!std::is_constructible<any, std::unique_ptr<int>>::value);
70static_assert(!std::is_assignable<any&, const std::unique_ptr<int>&>::value);
71static_assert(!std::is_constructible<any&, const std::unique_ptr<int>&>::value);
72static_assert(!std::is_assignable<any&, std::unique_ptr<int>&>::value);
73static_assert(!std::is_constructible<any&, std::unique_ptr<int>&>::value);
74
76{
77 NoDefaultCtor() = delete;
78};
79
80static_assert(!std::is_constructible_v<any,
81 std::in_place_type_t<NoDefaultCtor>>);
82
83static_assert(!std::is_constructible_v<any,
84 std::in_place_type_t<NoDefaultCtor>&>);
85
86static_assert(!std::is_constructible_v<any,
87 std::in_place_type_t<NoDefaultCtor>&&>);
88
89static_assert(!std::is_constructible_v<any,
90 const std::in_place_type_t<NoDefaultCtor>&>);
91
92static_assert(!std::is_constructible_v<any,
93 const std::in_place_type_t<NoDefaultCtor>&&>);
94
95static_assert( std::is_copy_constructible_v<std::tuple<any>> );
96
97namespace
98{
99struct A {
100 A(const A&) = default;
101 explicit A(any value);
102};
103} // namespace
104static_assert(std::is_copy_constructible_v<A>);
105
106BOOST_AUTO_TEST_SUITE( ki_any )
107
108struct combined {
109 std::vector<int> v;
110 std::tuple<int, int> t;
111 template<class... Args>
112 combined(std::initializer_list<int> il, Args&&... args)
113 : v(il), t(std::forward<Args>(args)...)
114 {
115 }
116};
117
118
120{
121 using std::string;
122 using std::strcmp;
123
124 any x(5); // x holds int
125 BOOST_CHECK(any_cast<int>(x) == 5); // cast to value
126 any_cast<int&>(x) = 10; // cast to reference
127 BOOST_CHECK(any_cast<int>(x) == 10);
128
129 x = "Meow"; // x holds const char*
130 BOOST_CHECK(strcmp(any_cast<const char*>(x), "Meow") == 0);
131 any_cast<const char*&>(x) = "Harry";
132 BOOST_CHECK(strcmp(any_cast<const char*>(x), "Harry") == 0);
133
134 x = string("Meow"); // x holds string
135 string s, s2("Jane");
136 s = std::move(any_cast<string&>(x)); // move from any
137 BOOST_CHECK(s == "Meow");
138 any_cast<string&>(x) = std::move(s2); // move to any
139 BOOST_CHECK(any_cast<const string&>(x) == "Jane");
140
141 string cat("Meow");
142 const any y(cat); // const y holds string
143 BOOST_CHECK(any_cast<const string&>(y) == cat);
144}
145
146
148{
149 using ki::bad_any_cast;
150 any x(1);
151 auto p = any_cast<double>(&x);
152 BOOST_CHECK(p == nullptr);
153
154 x = 1.0;
155 p = any_cast<double>(&x);
156 BOOST_CHECK(p != nullptr);
157
158 x = any();
159 p = any_cast<double>(&x);
160 BOOST_CHECK(p == nullptr);
161
162 try {
164 BOOST_CHECK(false);
165 } catch (const bad_any_cast&) {
166 }
167}
168
169static int move_count = 0;
170
172{
173 struct MoveEnabled
174 {
175 MoveEnabled(MoveEnabled&&)
176 {
177 ++move_count;
178 }
179 MoveEnabled() = default;
180 MoveEnabled(const MoveEnabled&) = default;
181 };
182 MoveEnabled m;
183 MoveEnabled m2 = any_cast<MoveEnabled>(any(m));
184 BOOST_CHECK(move_count == 1);
185 MoveEnabled&& m3 = any_cast<MoveEnabled&&>(any(m));
186 BOOST_CHECK(move_count == 1);
187}
188
189
191{
192 struct ExplicitCopy
193 {
194 ExplicitCopy() = default;
195 explicit ExplicitCopy(const ExplicitCopy&) = default;
196 };
197 any x = ExplicitCopy();
198 ExplicitCopy ec{any_cast<ExplicitCopy>(x)};
199 ExplicitCopy ec2{any_cast<ExplicitCopy>(std::move(x))};
200}
201
202
204{
205 struct noncopyable {
206 noncopyable(noncopyable const&) = delete;
207 };
208
209 any a;
210 auto p = any_cast<noncopyable>(&a);
211 BOOST_CHECK( p == nullptr );
212}
213
214
216{
217 // The contained value of a std::any is always an object type,
218 // but any_cast does not forbid checking for function types.
219
220 any a(1);
221 void (*p1)() = any_cast<void()>(&a);
222 BOOST_CHECK( p1 == nullptr );
223 int (*p2)(int) = any_cast<int(int)>(&a);
224 BOOST_CHECK( p2 == nullptr );
225 int (*p3)() = any_cast<int()>(&std::as_const(a));
226 BOOST_CHECK( p3 == nullptr );
227
228 try {
230 BOOST_CHECK( false );
231 } catch (const ki::bad_any_cast&) {
232 }
233
234 try {
235 any_cast<int(&)()>(std::move(a));
236 BOOST_CHECK( false );
237 } catch (const ki::bad_any_cast&) {
238 }
239
240 try {
241 any_cast<int(&)()>(std::as_const(a));
242 BOOST_CHECK( false );
243 } catch (const ki::bad_any_cast&) {
244 }
245}
246
247
249{
250 int arr[3];
251 any a(arr);
252
253 BOOST_CHECK( a.type() == typeid(int*) ); // contained value is decayed
254 int (*p1)[3] = any_cast<int[3]>(&a);
255 BOOST_CHECK( a.type() != typeid(int[3]) ); // so any_cast should return nullptr
256 BOOST_CHECK( p1 == nullptr );
257 int (*p2)[] = any_cast<int[]>(&a);
258 BOOST_CHECK( a.type() != typeid(int[]) ); // so any_cast should return nullptr
259 BOOST_CHECK( p2 == nullptr );
260 const int (*p3)[] = any_cast<int[]>(&std::as_const(a));
261 BOOST_CHECK( p3 == nullptr );
262}
263
264
266{
268 ~LocationAware() { BOOST_CHECK(self == this); }
270 LocationAware& operator=(const LocationAware&) { return *this; }
272 LocationAware& operator=(LocationAware&&) noexcept { return *this; }
273
274 void* const self = this;
275};
276static_assert(std::is_nothrow_move_constructible<LocationAware>::value, "");
277static_assert(!std::is_trivially_copyable<LocationAware>::value, "");
278
279
280BOOST_AUTO_TEST_CASE( NonTrivialType_1 )
281{
283 any a = l;
284}
285
286
287BOOST_AUTO_TEST_CASE( NonTrivialType_2 )
288{
290 any a = l;
291 any b = a;
292 {
293 any tmp = std::move(a);
294 a = std::move(b);
295 b = std::move(tmp);
296 }
297}
298
299
300BOOST_AUTO_TEST_CASE( NonTrivialType_3 )
301{
303 any a = l;
304 any b = a;
305 swap(a, b);
306}
307
308
310{
311 const int i = 42;
312 auto o = ki::make_any<int>(i);
313 int& i2 = any_cast<int&>(o);
314 BOOST_CHECK( i2 == 42 );
315 BOOST_CHECK( &i2 != &i );
316 auto o2 = ki::make_any<std::tuple<int, int>>(1, 2);
317 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
318 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
319 auto o3 = ki::make_any<std::vector<int>>({42, 666});
320 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
321 BOOST_CHECK(v[0] == 42 && v[1] == 666);
322 auto o4 = ki::make_any<combined>({42, 666});
324 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
325 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
326 auto o5 = ki::make_any<combined>({1, 2}, 3, 4);
328 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
329 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
330}
331
332
333BOOST_AUTO_TEST_CASE( TypeObserver )
334{
335 any x;
336 BOOST_CHECK( x.type() == typeid(void) );
337 x = 1;
338 BOOST_CHECK( x.type() == typeid(int) );
339 x = any();
340 BOOST_CHECK( x.type() == typeid(void) );
341}
342
343
345{
346 any x(1);
347 any y;
348 swap(x, y);
349 BOOST_CHECK( !x.has_value() );
350 BOOST_CHECK( y.has_value() );
351}
352
353
355{
356 any x(1);
357 any y;
358 x.swap(y);
359 BOOST_CHECK( !x.has_value() );
360 BOOST_CHECK( y.has_value() );
361 x.swap(y);
362 BOOST_CHECK( x.has_value() );
363 BOOST_CHECK( !y.has_value() );
364
365 x.reset();
366 BOOST_CHECK( !x.has_value() );
367}
368
369
370BOOST_AUTO_TEST_CASE( Construction_InPlace_1 )
371{
372 const int i = 42;
373 any o(std::in_place_type<int>, i);
374 int& i2 = any_cast<int&>(o);
375 BOOST_CHECK( i2 == 42 );
376 BOOST_CHECK( &i2 != &i );
377 any o2(std::in_place_type<std::tuple<int, int>>, 1, 2);
378 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
379 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
380 any o3(std::in_place_type<std::vector<int>>, {42, 666});
381 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
382 BOOST_CHECK(v[0] == 42 && v[1] == 666);
383 any o4(std::in_place_type<combined>, {42, 666});
385 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
386 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
387 any o5(std::in_place_type<combined>, {1, 2}, 3, 4);
389 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
390 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
391 any o6(std::in_place_type<int&>, i);
392 BOOST_CHECK(o6.type() == o.type());
393 any o7(std::in_place_type<void()>, nullptr);
394 any o8(std::in_place_type<void(*)()>, nullptr);
395 BOOST_CHECK(o7.type() == o8.type());
396 any o9(std::in_place_type<char(&)[42]>, nullptr);
397 any o10(std::in_place_type<char*>, nullptr);
398 BOOST_CHECK(o9.type() == o10.type());
399}
400
401bool moved = false;
402bool copied = false;
403
404struct X
405{
406 X() = default;
407 X(const X&) { copied = true; }
408 X(X&&) { moved = true; }
409};
410
411struct X2
412{
413 X2() = default;
414 X2(const X2&) { copied = true; }
415 X2(X2&&) noexcept { moved = true; }
416};
417
418
419BOOST_AUTO_TEST_CASE( Construction_Basic_1 )
420{
421 moved = false;
422 X x;
423 any a1(x);
424 BOOST_CHECK(moved == false);
425 any a2(std::move(x));
426 BOOST_CHECK(moved == true);
427}
428
429
430BOOST_AUTO_TEST_CASE( Construction_Basic_2 )
431{
432 moved = false;
433 X x;
434 any a1(x);
435 BOOST_CHECK(moved == false);
436 copied = false;
437 any a2(std::move(a1));
438 BOOST_CHECK(copied == false);
439}
440
441
442BOOST_AUTO_TEST_CASE( Construction_Basic_3 )
443{
444 moved = false;
445 X2 x;
446 any a1(x);
447 BOOST_CHECK(moved == false);
448 copied = false;
449 any a2(std::move(a1));
450 BOOST_CHECK(copied == false);
451 BOOST_CHECK(moved == true);
452}
453
454
455BOOST_AUTO_TEST_CASE( Construction_Basic_4)
456{
457 any x;
458 BOOST_CHECK( !x.has_value() );
459
460 any y(x);
461 BOOST_CHECK( !x.has_value() );
462 BOOST_CHECK( !y.has_value() );
463
464 any z(std::move(y));
465 BOOST_CHECK( !y.has_value() );
466 BOOST_CHECK( !z.has_value() );
467}
468
469
470BOOST_AUTO_TEST_CASE( Construction_Basic_5)
471{
472 any x(1);
473 BOOST_CHECK( x.has_value() );
474
475 any y(x);
476 BOOST_CHECK( x.has_value() );
477 BOOST_CHECK( y.has_value() );
478
479 any z(std::move(y));
480 BOOST_CHECK( !y.has_value() );
481 BOOST_CHECK( z.has_value() );
482}
483
484
485BOOST_AUTO_TEST_CASE( Construction_InPlace_2 )
486{
487 auto a = any(std::in_place_type<any>, 5);
488 BOOST_CHECK( any_cast<int>(any_cast<any>(a)) == 5 );
489}
490
491
492BOOST_AUTO_TEST_CASE( Construction_Pair )
493{
494 any p = std::pair<any, any>(1, 1);
495 auto pt = any_cast<std::pair<any, any>>(p);
496 BOOST_CHECK( any_cast<int>(pt.first) == 1 );
497 BOOST_CHECK( any_cast<int>(pt.second) == 1 );
498
499 any t = std::tuple<any>(1);
500 auto tt = any_cast<std::tuple<any>>(t);
501 BOOST_CHECK( any_cast<int>(std::get<0>(tt)) == 1 );
502}
503
504
505// Alignment requiremnts of this type prevent it being stored in 'any'
506struct alignas(2 * alignof(void*)) X3 { };
507
508bool
509stored_internally(void* obj, const ki::any& a)
510{
511 std::uintptr_t a_addr = reinterpret_cast<std::uintptr_t>(&a);
512 std::uintptr_t a_end = a_addr + sizeof(a);
513 std::uintptr_t obj_addr = reinterpret_cast<std::uintptr_t>(obj);
514 return (a_addr <= obj_addr) && (obj_addr < a_end);
515}
516
517
518BOOST_AUTO_TEST_CASE( Construction_Alignment )
519{
520 any a = X3{};
521 X3& x = any_cast<X3&>(a);
522 BOOST_CHECK( !stored_internally(&x, a) );
523
524 a = 'X';
525 char& c = any_cast<char&>(a);
526 BOOST_CHECK( stored_internally(&c, a) );
527}
528
530{
531 wrapper() = default;
532
533 wrapper(const any& t);
534
535 wrapper(const wrapper& w);
536
537 auto& operator=(const any& t);
538
539 auto& operator=(const wrapper& w)
540 {
541 value = w.value;
542 return *this;
543 }
544
546};
547
548BOOST_AUTO_TEST_CASE( Construction_Wrapper )
549{
550 wrapper a, b;
551 a = b;
552}
553
554// Following tests commented out until Apple Clang build version >= 16
555/*
556struct aggressive_aggregate
557{
558 int a;
559 int b;
560};
561
562BOOST_AUTO_TEST_CASE( Construction_Aggregate_1 )
563{
564 any x{std::in_place_type<aggressive_aggregate>, 1, 2};
565 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
566 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 2);
567 any y{std::in_place_type<aggressive_aggregate>, 1};
568 BOOST_CHECK(any_cast<aggressive_aggregate>(y).a == 1);
569 BOOST_CHECK(any_cast<aggressive_aggregate>(y).b == 0);
570 any z{std::in_place_type<aggressive_aggregate>};
571 BOOST_CHECK(any_cast<aggressive_aggregate>(z).a == 0);
572 BOOST_CHECK(any_cast<aggressive_aggregate>(z).b == 0);
573}
574
575BOOST_AUTO_TEST_CASE( Construction_Aggregate_2 )
576{
577 any x;
578 x.emplace<aggressive_aggregate>(1, 2);
579 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
580 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 2);
581 x.emplace<aggressive_aggregate>(1);
582 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
583 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 0);
584 x.emplace<aggressive_aggregate>();
585 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 0);
586 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 0);
587}
588
589*/
590
591std::set<const void*> live_objects;
592
593struct A {
594 A() { live_objects.insert(this); }
595 ~A() { live_objects.erase(this); }
596 A(const A& a) { BOOST_CHECK(live_objects.count(&a)); live_objects.insert(this); }
597};
598
600{
601 any a;
602 a = a;
603 BOOST_CHECK( !a.has_value() );
604
605 a = A{};
606 a = a;
607 BOOST_CHECK( a.has_value() );
608
609 a.reset();
610 BOOST_CHECK( live_objects.empty() );
611}
612
613
615{
616 struct X {
617 any a;
618 };
619
620 X x;
621 std::swap(x, x); // results in "self-move-assignment" of X::a
622 BOOST_CHECK( !x.a.has_value() );
623
624 x.a = A{};
625 std::swap(x, x); // results in "self-move-assignment" of X::a
626 BOOST_CHECK( x.a.has_value() );
627
628 x.a.reset();
629 BOOST_CHECK( live_objects.empty() );
630}
631
632
634{
635 any a;
636 a.swap(a);
637 BOOST_CHECK( !a.has_value() );
638
639 a = A{};
640 a.swap(a);
641 BOOST_CHECK( a.has_value() );
642
643 a.reset();
644 BOOST_CHECK( live_objects.empty() );
645}
646
647
649{
650 moved = false;
651 X x;
652 any a1;
653 a1 = x;
654 BOOST_CHECK(moved == false);
655 any a2;
656 copied = false;
657 a2 = std::move(x);
658 BOOST_CHECK(moved == true);
659 BOOST_CHECK(copied == false);
660}
661
662
664{
665 moved = false;
666 X x;
667 any a1;
668 a1 = x;
669 BOOST_CHECK(moved == false);
670 any a2;
671 copied = false;
672 a2 = std::move(a1);
673 BOOST_CHECK(moved == false);
674 BOOST_CHECK(copied == false);
675}
676
677
679{
680 moved = false;
681 X2 x;
682 any a1;
683 a1 = x;
684 BOOST_CHECK(copied && moved);
685 any a2;
686 moved = false;
687 copied = false;
688 a2 = std::move(a1);
689 BOOST_CHECK(moved == true);
690 BOOST_CHECK(copied == false);
691}
692
694{
695 any x;
696 any y;
697 y = x;
698 BOOST_CHECK( !x.has_value() );
699 BOOST_CHECK( !y.has_value() );
700
701 y = std::move(x);
702 BOOST_CHECK( !x.has_value() );
703 BOOST_CHECK( !y.has_value() );
704}
705
707{
708 any x(1);
709 any y;
710 y = x;
711 BOOST_CHECK( x.has_value() );
712 BOOST_CHECK( y.has_value() );
713
714 x = std::move(y);
715 BOOST_CHECK( x.has_value() );
716 BOOST_CHECK( !y.has_value() );
717
718 x = y;
719 BOOST_CHECK( !x.has_value() );
720 BOOST_CHECK( !y.has_value() );
721}
722
723
724bool should_throw = false;
725struct Bad
726{
727 Bad() = default;
728 Bad(const Bad&) {if (should_throw) throw 666;}
729};
730
731struct Bad2
732{
733 Bad2() = default;
734 Bad2(const Bad2&) {if (should_throw) throw 666;}
735 Bad2(Bad2&&) noexcept {}
736};
737
738int del_count = 0;
739struct Good
740{
741 Good() = default;
742 Good(const Good&) = default;
743 Good(Good&&) = default;
745};
746
748{
749 any a1 = Good();
750 del_count = 0;
751 try {
752 Bad b;
753 any a2 = b;
754 should_throw = true;
755 a1 = a2;
756 } catch (...) {
757 auto x = any_cast<Good>(a1);
758 BOOST_CHECK( del_count == 0 );
759 BOOST_CHECK( a1.has_value() );
760 any_cast<Good>(a1);
761 }
762 any a3 = Good();
763 del_count = 0;
764 try {
765 Bad2 b;
766 any a4 = b;
767 should_throw = true;
768 a3 = a4;
769 } catch (...) {
770 auto x = any_cast<Good>(a1);
771 BOOST_CHECK( del_count == 0 );
772 BOOST_CHECK( a1.has_value() );
773 any_cast<Good>(a1);
774 }
775}
776
777
779{
780 const int i = 42;
781 any o;
782 o.emplace<int>(i);
783 int& i2 = any_cast<int&>(o);
784 BOOST_CHECK( i2 == 42 );
785 BOOST_CHECK( &i2 != &i );
786 any o2;
787 o2.emplace<std::tuple<int, int>>(1, 2);
788 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
789 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
790 any o3;
791 o3.emplace<std::vector<int>>({42, 666});
792 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
793 BOOST_CHECK(v[0] == 42 && v[1] == 666);
794 any o4;
795 o4.emplace<combined>({42, 666});
797 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
798 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
799 any o5;
800 o5.emplace<combined>({1, 2}, 3, 4);
802 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
803 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
804 any o6;
805 o6.emplace<const int&>(i);
806 BOOST_CHECK(o6.type() == o.type());
807 any o7;
808 o7.emplace<void()>(nullptr);
809 any o8;
810 o8.emplace<void(*)()>(nullptr);
811 BOOST_CHECK(o7.type() == o8.type());
812 any o9;
813 o9.emplace<char(&)[42]>(nullptr);
814 any o10;
815 o10.emplace<char*>(nullptr);
816 BOOST_CHECK(o9.type() == o10.type());
817 any o11;
818 BOOST_CHECK(&o11.emplace<int>(42) == &any_cast<int&>(o11));
819 BOOST_CHECK(&o11.emplace<std::vector<int>>({1,2,3}) ==
820 &any_cast<std::vector<int>&>(o11));
821}
822
823
824
825struct X_e
826{
827 X_e() = default;
828 X_e(const X_e&) { copied = true; }
829 X_e(X_e&&) { moved = true; }
830};
831
832struct X2_e
833{
834 X2_e() = default;
835 X2_e(const X2_e&) { copied = true; }
836 X2_e(X2_e&&) noexcept { moved = true; }
837};
838
839
A type-safe container of any type.
Definition ki_any.h:92
bool has_value() const noexcept
Report whether there is a contained object or not.
Definition ki_any.h:311
void reset() noexcept
If not empty, destroys the contained object.
Definition ki_any.h:271
void swap(any &rhs) noexcept
Exchange state with another object.
Definition ki_any.h:281
any_emplace_t< std::decay_t< T >, Args... > emplace(Args &&... args)
Emplace with an object created from args as the contained object.
Definition ki_any.h:253
const std::type_info & type() const noexcept
The typeid of the contained object, or typeid(void) if empty.
Definition ki_any.h:315
Exception class thrown by a failed any_cast.
Definition ki_any.h:80
An implementation of std::any_cast, which uses type_info::hash_code to check validity of cast types.
std::enable_if_t< std::is_constructible_v< any, std::in_place_type_t< T >, Args... >, any > make_any(Args &&... args)
Create a any holding a T constructed from args....
Definition ki_any.h:419
ValueType any_cast(const any &any)
Access the contained object.
Definition ki_any.h:445
STL namespace.
A(const A &a)
Bad2(Bad2 &&) noexcept
Bad2()=default
Bad2(const Bad2 &)
Bad(const Bad &)
Bad()=default
Good()=default
Good(const Good &)=default
Good(Good &&)=default
void *const self
LocationAware & operator=(const LocationAware &)
LocationAware(LocationAware &&) noexcept
LocationAware(const LocationAware &)
LocationAware & operator=(LocationAware &&) noexcept
NoDefaultCtor()=delete
X2_e(const X2_e &)
X2_e()=default
X2_e(X2_e &&) noexcept
X2()=default
X2(const X2 &)
X2(X2 &&) noexcept
X_e()=default
X_e(const X_e &)
X_e(X_e &&)
X()=default
X(X &&)
X(const X &)
std::vector< int > v
combined(std::initializer_list< int > il, Args &&... args)
std::tuple< int, int > t
wrapper(const any &t)
wrapper(const wrapper &w)
wrapper()=default
auto & operator=(const any &t)
auto & operator=(const wrapper &w)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
bool stored_internally(void *obj, const ki::any &a)
bool should_throw
bool copied
BOOST_AUTO_TEST_CASE(AnyCast_1)
std::set< const void * > live_objects
int del_count
bool moved
ValueType any_cast(const any &any)
Access the contained object.
Definition ki_any.h:445
static int move_count
MATRIX3x3D m2(VECTOR3I{ 6, 6, 6 }, { 1, 1, 1 }, { 3, 3, 3 })
Test suite for KiCad math code.
MATRIX3x3D m3(VECTOR3I{ 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 })