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 along
17 * with this program. If not, see <http://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// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
41// <http://www.gnu.org/licenses/>.
42
43#include <boost/test/unit_test.hpp>
44
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
97struct A {
98 A(const A&) = default;
99 explicit A(any value);
100};
101static_assert(std::is_copy_constructible_v<A>);
102
103BOOST_AUTO_TEST_SUITE( ki_any )
104
105struct combined {
106 std::vector<int> v;
107 std::tuple<int, int> t;
108 template<class... Args>
109 combined(std::initializer_list<int> il, Args&&... args)
110 : v(il), t(std::forward<Args>(args)...)
111 {
112 }
113};
114
115
117{
118 using std::string;
119 using std::strcmp;
120
121 any x(5); // x holds int
122 BOOST_CHECK(any_cast<int>(x) == 5); // cast to value
123 any_cast<int&>(x) = 10; // cast to reference
124 BOOST_CHECK(any_cast<int>(x) == 10);
125
126 x = "Meow"; // x holds const char*
127 BOOST_CHECK(strcmp(any_cast<const char*>(x), "Meow") == 0);
128 any_cast<const char*&>(x) = "Harry";
129 BOOST_CHECK(strcmp(any_cast<const char*>(x), "Harry") == 0);
130
131 x = string("Meow"); // x holds string
132 string s, s2("Jane");
133 s = std::move(any_cast<string&>(x)); // move from any
134 BOOST_CHECK(s == "Meow");
135 any_cast<string&>(x) = std::move(s2); // move to any
136 BOOST_CHECK(any_cast<const string&>(x) == "Jane");
137
138 string cat("Meow");
139 const any y(cat); // const y holds string
140 BOOST_CHECK(any_cast<const string&>(y) == cat);
141}
142
143
145{
146 using ki::bad_any_cast;
147 any x(1);
148 auto p = any_cast<double>(&x);
149 BOOST_CHECK(p == nullptr);
150
151 x = 1.0;
152 p = any_cast<double>(&x);
153 BOOST_CHECK(p != nullptr);
154
155 x = any();
156 p = any_cast<double>(&x);
157 BOOST_CHECK(p == nullptr);
158
159 try {
160 any_cast<double>(x);
161 BOOST_CHECK(false);
162 } catch (const bad_any_cast&) {
163 }
164}
165
166static int move_count = 0;
167
169{
170 struct MoveEnabled
171 {
172 MoveEnabled(MoveEnabled&&)
173 {
174 ++move_count;
175 }
176 MoveEnabled() = default;
177 MoveEnabled(const MoveEnabled&) = default;
178 };
179 MoveEnabled m;
180 MoveEnabled m2 = any_cast<MoveEnabled>(any(m));
181 BOOST_CHECK(move_count == 1);
182 MoveEnabled&& m3 = any_cast<MoveEnabled&&>(any(m));
183 BOOST_CHECK(move_count == 1);
184}
185
186
188{
189 struct ExplicitCopy
190 {
191 ExplicitCopy() = default;
192 explicit ExplicitCopy(const ExplicitCopy&) = default;
193 };
194 any x = ExplicitCopy();
195 ExplicitCopy ec{any_cast<ExplicitCopy>(x)};
196 ExplicitCopy ec2{any_cast<ExplicitCopy>(std::move(x))};
197}
198
199
201{
202 struct noncopyable {
203 noncopyable(noncopyable const&) = delete;
204 };
205
206 any a;
207 auto p = any_cast<noncopyable>(&a);
208 BOOST_CHECK( p == nullptr );
209}
210
211
213{
214 // The contained value of a std::any is always an object type,
215 // but any_cast does not forbid checking for function types.
216
217 any a(1);
218 void (*p1)() = any_cast<void()>(&a);
219 BOOST_CHECK( p1 == nullptr );
220 int (*p2)(int) = any_cast<int(int)>(&a);
221 BOOST_CHECK( p2 == nullptr );
222 int (*p3)() = any_cast<int()>(&std::as_const(a));
223 BOOST_CHECK( p3 == nullptr );
224
225 try {
226 any_cast<int(&)()>(a);
227 BOOST_CHECK( false );
228 } catch (const ki::bad_any_cast&) {
229 }
230
231 try {
232 any_cast<int(&)()>(std::move(a));
233 BOOST_CHECK( false );
234 } catch (const ki::bad_any_cast&) {
235 }
236
237 try {
238 any_cast<int(&)()>(std::as_const(a));
239 BOOST_CHECK( false );
240 } catch (const ki::bad_any_cast&) {
241 }
242}
243
244
246{
247 int arr[3];
248 any a(arr);
249
250 BOOST_CHECK( a.type() == typeid(int*) ); // contained value is decayed
251 int (*p1)[3] = any_cast<int[3]>(&a);
252 BOOST_CHECK( a.type() != typeid(int[3]) ); // so any_cast should return nullptr
253 BOOST_CHECK( p1 == nullptr );
254 int (*p2)[] = any_cast<int[]>(&a);
255 BOOST_CHECK( a.type() != typeid(int[]) ); // so any_cast should return nullptr
256 BOOST_CHECK( p2 == nullptr );
257 const int (*p3)[] = any_cast<int[]>(&std::as_const(a));
258 BOOST_CHECK( p3 == nullptr );
259}
260
261
263{
265 ~LocationAware() { BOOST_CHECK(self == this); }
267 LocationAware& operator=(const LocationAware&) { return *this; }
269 LocationAware& operator=(LocationAware&&) noexcept { return *this; }
270
271 void* const self = this;
272};
273static_assert(std::is_nothrow_move_constructible<LocationAware>::value, "");
274static_assert(!std::is_trivially_copyable<LocationAware>::value, "");
275
276
277BOOST_AUTO_TEST_CASE( NonTrivialType_1 )
278{
280 any a = l;
281}
282
283
284BOOST_AUTO_TEST_CASE( NonTrivialType_2 )
285{
287 any a = l;
288 any b = a;
289 {
290 any tmp = std::move(a);
291 a = std::move(b);
292 b = std::move(tmp);
293 }
294}
295
296
297BOOST_AUTO_TEST_CASE( NonTrivialType_3 )
298{
300 any a = l;
301 any b = a;
302 swap(a, b);
303}
304
305
307{
308 const int i = 42;
309 auto o = ki::make_any<int>(i);
310 int& i2 = any_cast<int&>(o);
311 BOOST_CHECK( i2 == 42 );
312 BOOST_CHECK( &i2 != &i );
313 auto o2 = ki::make_any<std::tuple<int, int>>(1, 2);
314 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
315 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
316 auto o3 = ki::make_any<std::vector<int>>({42, 666});
317 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
318 BOOST_CHECK(v[0] == 42 && v[1] == 666);
319 auto o4 = ki::make_any<combined>({42, 666});
320 combined& c = any_cast<combined&>(o4);
321 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
322 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
323 auto o5 = ki::make_any<combined>({1, 2}, 3, 4);
324 combined& c2 = any_cast<combined&>(o5);
325 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
326 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
327}
328
329
330BOOST_AUTO_TEST_CASE( TypeObserver )
331{
332 any x;
333 BOOST_CHECK( x.type() == typeid(void) );
334 x = 1;
335 BOOST_CHECK( x.type() == typeid(int) );
336 x = any();
337 BOOST_CHECK( x.type() == typeid(void) );
338}
339
340
342{
343 any x(1);
344 any y;
345 swap(x, y);
346 BOOST_CHECK( !x.has_value() );
347 BOOST_CHECK( y.has_value() );
348}
349
350
352{
353 any x(1);
354 any y;
355 x.swap(y);
356 BOOST_CHECK( !x.has_value() );
357 BOOST_CHECK( y.has_value() );
358 x.swap(y);
359 BOOST_CHECK( x.has_value() );
360 BOOST_CHECK( !y.has_value() );
361
362 x.reset();
363 BOOST_CHECK( !x.has_value() );
364}
365
366
367BOOST_AUTO_TEST_CASE( Construction_InPlace_1 )
368{
369 const int i = 42;
370 any o(std::in_place_type<int>, i);
371 int& i2 = any_cast<int&>(o);
372 BOOST_CHECK( i2 == 42 );
373 BOOST_CHECK( &i2 != &i );
374 any o2(std::in_place_type<std::tuple<int, int>>, 1, 2);
375 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
376 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
377 any o3(std::in_place_type<std::vector<int>>, {42, 666});
378 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
379 BOOST_CHECK(v[0] == 42 && v[1] == 666);
380 any o4(std::in_place_type<combined>, {42, 666});
381 combined& c = any_cast<combined&>(o4);
382 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
383 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
384 any o5(std::in_place_type<combined>, {1, 2}, 3, 4);
385 combined& c2 = any_cast<combined&>(o5);
386 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
387 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
388 any o6(std::in_place_type<int&>, i);
389 BOOST_CHECK(o6.type() == o.type());
390 any o7(std::in_place_type<void()>, nullptr);
391 any o8(std::in_place_type<void(*)()>, nullptr);
392 BOOST_CHECK(o7.type() == o8.type());
393 any o9(std::in_place_type<char(&)[42]>, nullptr);
394 any o10(std::in_place_type<char*>, nullptr);
395 BOOST_CHECK(o9.type() == o10.type());
396}
397
398bool moved = false;
399bool copied = false;
400
401struct X
402{
403 X() = default;
404 X(const X&) { copied = true; }
405 X(X&&) { moved = true; }
406};
407
408struct X2
409{
410 X2() = default;
411 X2(const X2&) { copied = true; }
412 X2(X2&&) noexcept { moved = true; }
413};
414
415
416BOOST_AUTO_TEST_CASE( Construction_Basic_1 )
417{
418 moved = false;
419 X x;
420 any a1(x);
421 BOOST_CHECK(moved == false);
422 any a2(std::move(x));
423 BOOST_CHECK(moved == true);
424}
425
426
427BOOST_AUTO_TEST_CASE( Construction_Basic_2 )
428{
429 moved = false;
430 X x;
431 any a1(x);
432 BOOST_CHECK(moved == false);
433 copied = false;
434 any a2(std::move(a1));
435 BOOST_CHECK(copied == false);
436}
437
438
439BOOST_AUTO_TEST_CASE( Construction_Basic_3 )
440{
441 moved = false;
442 X2 x;
443 any a1(x);
444 BOOST_CHECK(moved == false);
445 copied = false;
446 any a2(std::move(a1));
447 BOOST_CHECK(copied == false);
448 BOOST_CHECK(moved == true);
449}
450
451
452BOOST_AUTO_TEST_CASE( Construction_Basic_4)
453{
454 any x;
455 BOOST_CHECK( !x.has_value() );
456
457 any y(x);
458 BOOST_CHECK( !x.has_value() );
459 BOOST_CHECK( !y.has_value() );
460
461 any z(std::move(y));
462 BOOST_CHECK( !y.has_value() );
463 BOOST_CHECK( !z.has_value() );
464}
465
466
467BOOST_AUTO_TEST_CASE( Construction_Basic_5)
468{
469 any x(1);
470 BOOST_CHECK( x.has_value() );
471
472 any y(x);
473 BOOST_CHECK( x.has_value() );
474 BOOST_CHECK( y.has_value() );
475
476 any z(std::move(y));
477 BOOST_CHECK( !y.has_value() );
478 BOOST_CHECK( z.has_value() );
479}
480
481
482BOOST_AUTO_TEST_CASE( Construction_InPlace_2 )
483{
484 auto a = any(std::in_place_type<any>, 5);
485 BOOST_CHECK( any_cast<int>(any_cast<any>(a)) == 5 );
486}
487
488
489BOOST_AUTO_TEST_CASE( Construction_Pair )
490{
491 any p = std::pair<any, any>(1, 1);
492 auto pt = any_cast<std::pair<any, any>>(p);
493 BOOST_CHECK( any_cast<int>(pt.first) == 1 );
494 BOOST_CHECK( any_cast<int>(pt.second) == 1 );
495
496 any t = std::tuple<any>(1);
497 auto tt = any_cast<std::tuple<any>>(t);
498 BOOST_CHECK( any_cast<int>(std::get<0>(tt)) == 1 );
499}
500
501
502// Alignment requiremnts of this type prevent it being stored in 'any'
503struct alignas(2 * alignof(void*)) X3 { };
504
505bool
506stored_internally(void* obj, const ki::any& a)
507{
508 std::uintptr_t a_addr = reinterpret_cast<std::uintptr_t>(&a);
509 std::uintptr_t a_end = a_addr + sizeof(a);
510 std::uintptr_t obj_addr = reinterpret_cast<std::uintptr_t>(obj);
511 return (a_addr <= obj_addr) && (obj_addr < a_end);
512}
513
514
515BOOST_AUTO_TEST_CASE( Construction_Alignment )
516{
517 any a = X3{};
518 X3& x = any_cast<X3&>(a);
519 BOOST_CHECK( !stored_internally(&x, a) );
520
521 a = 'X';
522 char& c = any_cast<char&>(a);
523 BOOST_CHECK( stored_internally(&c, a) );
524}
525
527{
528 wrapper() = default;
529
530 wrapper(const any& t);
531
532 wrapper(const wrapper& w);
533
534 auto& operator=(const any& t);
535
536 auto& operator=(const wrapper& w)
537 {
538 value = w.value;
539 return *this;
540 }
541
543};
544
545BOOST_AUTO_TEST_CASE( Construction_Wrapper )
546{
547 wrapper a, b;
548 a = b;
549}
550
551// Following tests commented out until Apple Clang build version >= 16
552/*
553struct aggressive_aggregate
554{
555 int a;
556 int b;
557};
558
559BOOST_AUTO_TEST_CASE( Construction_Aggregate_1 )
560{
561 any x{std::in_place_type<aggressive_aggregate>, 1, 2};
562 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
563 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 2);
564 any y{std::in_place_type<aggressive_aggregate>, 1};
565 BOOST_CHECK(any_cast<aggressive_aggregate>(y).a == 1);
566 BOOST_CHECK(any_cast<aggressive_aggregate>(y).b == 0);
567 any z{std::in_place_type<aggressive_aggregate>};
568 BOOST_CHECK(any_cast<aggressive_aggregate>(z).a == 0);
569 BOOST_CHECK(any_cast<aggressive_aggregate>(z).b == 0);
570}
571
572BOOST_AUTO_TEST_CASE( Construction_Aggregate_2 )
573{
574 any x;
575 x.emplace<aggressive_aggregate>(1, 2);
576 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
577 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 2);
578 x.emplace<aggressive_aggregate>(1);
579 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 1);
580 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 0);
581 x.emplace<aggressive_aggregate>();
582 BOOST_CHECK(any_cast<aggressive_aggregate>(x).a == 0);
583 BOOST_CHECK(any_cast<aggressive_aggregate>(x).b == 0);
584}
585
586*/
587
588std::set<const void*> live_objects;
589
590struct A {
591 A() { live_objects.insert(this); }
592 ~A() { live_objects.erase(this); }
593 A(const A& a) { BOOST_CHECK(live_objects.count(&a)); live_objects.insert(this); }
594};
595
597{
598 any a;
599 a = a;
600 BOOST_CHECK( !a.has_value() );
601
602 a = A{};
603 a = a;
604 BOOST_CHECK( a.has_value() );
605
606 a.reset();
607 BOOST_CHECK( live_objects.empty() );
608}
609
610
612{
613 struct X {
614 any a;
615 };
616
617 X x;
618 std::swap(x, x); // results in "self-move-assignment" of X::a
619 BOOST_CHECK( !x.a.has_value() );
620
621 x.a = A{};
622 std::swap(x, x); // results in "self-move-assignment" of X::a
623 BOOST_CHECK( x.a.has_value() );
624
625 x.a.reset();
626 BOOST_CHECK( live_objects.empty() );
627}
628
629
631{
632 any a;
633 a.swap(a);
634 BOOST_CHECK( !a.has_value() );
635
636 a = A{};
637 a.swap(a);
638 BOOST_CHECK( a.has_value() );
639
640 a.reset();
641 BOOST_CHECK( live_objects.empty() );
642}
643
644
646{
647 moved = false;
648 X x;
649 any a1;
650 a1 = x;
651 BOOST_CHECK(moved == false);
652 any a2;
653 copied = false;
654 a2 = std::move(x);
655 BOOST_CHECK(moved == true);
656 BOOST_CHECK(copied == false);
657}
658
659
661{
662 moved = false;
663 X x;
664 any a1;
665 a1 = x;
666 BOOST_CHECK(moved == false);
667 any a2;
668 copied = false;
669 a2 = std::move(a1);
670 BOOST_CHECK(moved == false);
671 BOOST_CHECK(copied == false);
672}
673
674
676{
677 moved = false;
678 X2 x;
679 any a1;
680 a1 = x;
681 BOOST_CHECK(copied && moved);
682 any a2;
683 moved = false;
684 copied = false;
685 a2 = std::move(a1);
686 BOOST_CHECK(moved == true);
687 BOOST_CHECK(copied == false);
688}
689
691{
692 any x;
693 any y;
694 y = x;
695 BOOST_CHECK( !x.has_value() );
696 BOOST_CHECK( !y.has_value() );
697
698 y = std::move(x);
699 BOOST_CHECK( !x.has_value() );
700 BOOST_CHECK( !y.has_value() );
701}
702
704{
705 any x(1);
706 any y;
707 y = x;
708 BOOST_CHECK( x.has_value() );
709 BOOST_CHECK( y.has_value() );
710
711 x = std::move(y);
712 BOOST_CHECK( x.has_value() );
713 BOOST_CHECK( !y.has_value() );
714
715 x = y;
716 BOOST_CHECK( !x.has_value() );
717 BOOST_CHECK( !y.has_value() );
718}
719
720
721bool should_throw = false;
722struct Bad
723{
724 Bad() = default;
725 Bad(const Bad&) {if (should_throw) throw 666;}
726};
727
728struct Bad2
729{
730 Bad2() = default;
731 Bad2(const Bad2&) {if (should_throw) throw 666;}
732 Bad2(Bad2&&) noexcept {}
733};
734
735int del_count = 0;
736struct Good
737{
738 Good() = default;
739 Good(const Good&) = default;
740 Good(Good&&) = default;
742};
743
745{
746 any a1 = Good();
747 del_count = 0;
748 try {
749 Bad b;
750 any a2 = b;
751 should_throw = true;
752 a1 = a2;
753 } catch (...) {
754 auto x = any_cast<Good>(a1);
755 BOOST_CHECK( del_count == 0 );
756 BOOST_CHECK( a1.has_value() );
757 any_cast<Good>(a1);
758 }
759 any a3 = Good();
760 del_count = 0;
761 try {
762 Bad2 b;
763 any a4 = b;
764 should_throw = true;
765 a3 = a4;
766 } catch (...) {
767 auto x = any_cast<Good>(a1);
768 BOOST_CHECK( del_count == 0 );
769 BOOST_CHECK( a1.has_value() );
770 any_cast<Good>(a1);
771 }
772}
773
774
776{
777 const int i = 42;
778 any o;
779 o.emplace<int>(i);
780 int& i2 = any_cast<int&>(o);
781 BOOST_CHECK( i2 == 42 );
782 BOOST_CHECK( &i2 != &i );
783 any o2;
784 o2.emplace<std::tuple<int, int>>(1, 2);
785 std::tuple<int, int>& t = any_cast<std::tuple<int, int>&>(o2);
786 BOOST_CHECK( std::get<0>(t) == 1 && std::get<1>(t) == 2);
787 any o3;
788 o3.emplace<std::vector<int>>({42, 666});
789 std::vector<int>& v = any_cast<std::vector<int>&>(o3);
790 BOOST_CHECK(v[0] == 42 && v[1] == 666);
791 any o4;
792 o4.emplace<combined>({42, 666});
793 combined& c = any_cast<combined&>(o4);
794 BOOST_CHECK(c.v[0] == 42 && c.v[1] == 666
795 && std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
796 any o5;
797 o5.emplace<combined>({1, 2}, 3, 4);
798 combined& c2 = any_cast<combined&>(o5);
799 BOOST_CHECK(c2.v[0] == 1 && c2.v[1] == 2
800 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
801 any o6;
802 o6.emplace<const int&>(i);
803 BOOST_CHECK(o6.type() == o.type());
804 any o7;
805 o7.emplace<void()>(nullptr);
806 any o8;
807 o8.emplace<void(*)()>(nullptr);
808 BOOST_CHECK(o7.type() == o8.type());
809 any o9;
810 o9.emplace<char(&)[42]>(nullptr);
811 any o10;
812 o10.emplace<char*>(nullptr);
813 BOOST_CHECK(o9.type() == o10.type());
814 any o11;
815 BOOST_CHECK(&o11.emplace<int>(42) == &any_cast<int&>(o11));
816 BOOST_CHECK(&o11.emplace<std::vector<int>>({1,2,3}) ==
817 &any_cast<std::vector<int>&>(o11));
818}
819
820
821
822struct X_e
823{
824 X_e() = default;
825 X_e(const X_e&) { copied = true; }
826 X_e(X_e&&) { moved = true; }
827};
828
829struct X2_e
830{
831 X2_e() = default;
832 X2_e(const X2_e&) { copied = true; }
833 X2_e(X2_e&&) noexcept { moved = true; }
834};
835
836
A type-safe container of any type.
Definition: ki_any.h:93
bool has_value() const noexcept
Report whether there is a contained object or not.
Definition: ki_any.h:312
void reset() noexcept
If not empty, destroys the contained object.
Definition: ki_any.h:272
void swap(any &rhs) noexcept
Exchange state with another object.
Definition: ki_any.h:282
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:254
const std::type_info & type() const noexcept
The typeid of the contained object, or typeid(void) if empty.
Definition: ki_any.h:316
Exception class thrown by a failed any_cast.
Definition: ki_any.h:81
An implementation of std::any_cast, which uses type_info::hash_code to check validity of cast types.
ValueType any_cast(const any &any)
Access the contained object.
Definition: ki_any.h:446
STL namespace.
A(any value)
~A()
A(const A &)=default
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
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 })