138236b57SEric Fiselier //===----------------------------------------------------------------------===//
238236b57SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
638236b57SEric Fiselier //
738236b57SEric Fiselier //===----------------------------------------------------------------------===//
8*480cd780SLouis Dionne
93461dbc0SEric Fiselier #ifndef ANY_HELPERS_H
103461dbc0SEric Fiselier #define ANY_HELPERS_H
113461dbc0SEric Fiselier
123461dbc0SEric Fiselier #include <typeinfo>
133461dbc0SEric Fiselier #include <type_traits>
143461dbc0SEric Fiselier #include <cassert>
153461dbc0SEric Fiselier
16324506b9SEric Fiselier namespace std { namespace experimental {} }
17324506b9SEric Fiselier
183461dbc0SEric Fiselier #include "test_macros.h"
19324506b9SEric Fiselier #include "type_id.h"
203461dbc0SEric Fiselier
213461dbc0SEric Fiselier #if !defined(TEST_HAS_NO_RTTI)
223461dbc0SEric Fiselier #define RTTI_ASSERT(X) assert(X)
233461dbc0SEric Fiselier #else
243461dbc0SEric Fiselier #define RTTI_ASSERT(X)
253461dbc0SEric Fiselier #endif
263461dbc0SEric Fiselier
27aae63566SStephan T. Lavavej template <class T>
283461dbc0SEric Fiselier struct IsSmallObject
293461dbc0SEric Fiselier : public std::integral_constant<bool
30ffc83995SCasey Carter , sizeof(T) <= sizeof(std::any) - sizeof(void*)
313461dbc0SEric Fiselier && std::alignment_of<void*>::value
32aae63566SStephan T. Lavavej % std::alignment_of<T>::value == 0
33aae63566SStephan T. Lavavej && std::is_nothrow_move_constructible<T>::value
343461dbc0SEric Fiselier >
353461dbc0SEric Fiselier {};
363461dbc0SEric Fiselier
37324506b9SEric Fiselier template <class T>
containsType(std::any const & a)38324506b9SEric Fiselier bool containsType(std::any const& a) {
39324506b9SEric Fiselier #if !defined(TEST_HAS_NO_RTTI)
40324506b9SEric Fiselier return a.type() == typeid(T);
41324506b9SEric Fiselier #else
42324506b9SEric Fiselier return a.has_value() && std::any_cast<T>(&a) != nullptr;
43324506b9SEric Fiselier #endif
44324506b9SEric Fiselier }
453461dbc0SEric Fiselier
463461dbc0SEric Fiselier // Return 'true' if 'Type' will be considered a small type by 'any'
473461dbc0SEric Fiselier template <class Type>
isSmallType()483461dbc0SEric Fiselier bool isSmallType() {
493461dbc0SEric Fiselier return IsSmallObject<Type>::value;
503461dbc0SEric Fiselier }
513461dbc0SEric Fiselier
523461dbc0SEric Fiselier // Assert that an object is empty. If the object used to contain an object
533461dbc0SEric Fiselier // of type 'LastType' check that it can no longer be accessed.
543461dbc0SEric Fiselier template <class LastType = int>
assertEmpty(std::any const & a)55324506b9SEric Fiselier void assertEmpty(std::any const& a) {
56324506b9SEric Fiselier assert(!a.has_value());
573461dbc0SEric Fiselier RTTI_ASSERT(a.type() == typeid(void));
58ef2cdfe3SLouis Dionne assert(std::any_cast<LastType const>(&a) == nullptr);
593461dbc0SEric Fiselier }
603461dbc0SEric Fiselier
6150253ed1SEric Fiselier template <class Type>
6250253ed1SEric Fiselier constexpr auto has_value_member(int) -> decltype(std::declval<Type&>().value, true)
6350253ed1SEric Fiselier { return true; }
has_value_member(long)6450253ed1SEric Fiselier template <class> constexpr bool has_value_member(long) { return false; }
6550253ed1SEric Fiselier
6650253ed1SEric Fiselier
673461dbc0SEric Fiselier // Assert that an 'any' object stores the specified 'Type' and 'value'.
683461dbc0SEric Fiselier template <class Type>
6950253ed1SEric Fiselier std::enable_if_t<has_value_member<Type>(0)>
708a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
assertContains(std::any const & a,int value)7150253ed1SEric Fiselier assertContains(std::any const& a, int value) {
72324506b9SEric Fiselier assert(a.has_value());
73324506b9SEric Fiselier assert(containsType<Type>(a));
74324506b9SEric Fiselier assert(std::any_cast<Type const &>(a).value == value);
75324506b9SEric Fiselier }
76324506b9SEric Fiselier
7750253ed1SEric Fiselier template <class Type, class Value>
7850253ed1SEric Fiselier std::enable_if_t<!has_value_member<Type>(0)>
798a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
assertContains(std::any const & a,Value value)8050253ed1SEric Fiselier assertContains(std::any const& a, Value value) {
81324506b9SEric Fiselier assert(a.has_value());
8250253ed1SEric Fiselier assert(containsType<Type>(a));
8350253ed1SEric Fiselier assert(std::any_cast<Type const &>(a) == value);
843461dbc0SEric Fiselier }
853461dbc0SEric Fiselier
8650253ed1SEric Fiselier
873461dbc0SEric Fiselier // Modify the value of a "test type" stored within an any to the specified
883461dbc0SEric Fiselier // 'value'.
893461dbc0SEric Fiselier template <class Type>
908a063df1SLouis Dionne _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
modifyValue(std::any & a,int value)91324506b9SEric Fiselier void modifyValue(std::any& a, int value) {
92324506b9SEric Fiselier assert(a.has_value());
93324506b9SEric Fiselier assert(containsType<Type>(a));
94ef2cdfe3SLouis Dionne std::any_cast<Type&>(a).value = value;
953461dbc0SEric Fiselier }
963461dbc0SEric Fiselier
973461dbc0SEric Fiselier // A test type that will trigger the small object optimization within 'any'.
983461dbc0SEric Fiselier template <int Dummy = 0>
993461dbc0SEric Fiselier struct small_type
1003461dbc0SEric Fiselier {
1013461dbc0SEric Fiselier static int count;
1023461dbc0SEric Fiselier static int copied;
1033461dbc0SEric Fiselier static int moved;
1043461dbc0SEric Fiselier static int const_copied;
1053461dbc0SEric Fiselier static int non_const_copied;
1063461dbc0SEric Fiselier
resetsmall_type1073461dbc0SEric Fiselier static void reset() {
1083461dbc0SEric Fiselier small_type::copied = 0;
1093461dbc0SEric Fiselier small_type::moved = 0;
1103461dbc0SEric Fiselier small_type::const_copied = 0;
1113461dbc0SEric Fiselier small_type::non_const_copied = 0;
1123461dbc0SEric Fiselier }
1133461dbc0SEric Fiselier
1143461dbc0SEric Fiselier int value;
1153461dbc0SEric Fiselier
valuesmall_type116324506b9SEric Fiselier explicit small_type(int val = 0) : value(val) {
117324506b9SEric Fiselier ++count;
118324506b9SEric Fiselier }
small_typesmall_type119324506b9SEric Fiselier explicit small_type(int, int val, int) : value(val) {
120324506b9SEric Fiselier ++count;
121324506b9SEric Fiselier }
small_typesmall_type122324506b9SEric Fiselier small_type(std::initializer_list<int> il) : value(*il.begin()) {
1233461dbc0SEric Fiselier ++count;
1243461dbc0SEric Fiselier }
1253461dbc0SEric Fiselier
small_typesmall_type126324506b9SEric Fiselier small_type(small_type const & other) noexcept {
1273461dbc0SEric Fiselier value = other.value;
1283461dbc0SEric Fiselier ++count;
1293461dbc0SEric Fiselier ++copied;
1303461dbc0SEric Fiselier ++const_copied;
1313461dbc0SEric Fiselier }
1323461dbc0SEric Fiselier
small_typesmall_type133324506b9SEric Fiselier small_type(small_type& other) noexcept {
1343461dbc0SEric Fiselier value = other.value;
1353461dbc0SEric Fiselier ++count;
1363461dbc0SEric Fiselier ++copied;
1373461dbc0SEric Fiselier ++non_const_copied;
1383461dbc0SEric Fiselier }
1393461dbc0SEric Fiselier
small_typesmall_type140324506b9SEric Fiselier small_type(small_type && other) noexcept {
1413461dbc0SEric Fiselier value = other.value;
1423461dbc0SEric Fiselier other.value = 0;
1433461dbc0SEric Fiselier ++count;
1443461dbc0SEric Fiselier ++moved;
1453461dbc0SEric Fiselier }
1463461dbc0SEric Fiselier
~small_typesmall_type1473461dbc0SEric Fiselier ~small_type() {
1483461dbc0SEric Fiselier value = -1;
1493461dbc0SEric Fiselier --count;
1503461dbc0SEric Fiselier }
1513461dbc0SEric Fiselier
1523461dbc0SEric Fiselier private:
1533461dbc0SEric Fiselier small_type& operator=(small_type const&) = delete;
1543461dbc0SEric Fiselier small_type& operator=(small_type&&) = delete;
1553461dbc0SEric Fiselier };
1563461dbc0SEric Fiselier
1573461dbc0SEric Fiselier template <int Dummy>
1583461dbc0SEric Fiselier int small_type<Dummy>::count = 0;
1593461dbc0SEric Fiselier
1603461dbc0SEric Fiselier template <int Dummy>
1613461dbc0SEric Fiselier int small_type<Dummy>::copied = 0;
1623461dbc0SEric Fiselier
1633461dbc0SEric Fiselier template <int Dummy>
1643461dbc0SEric Fiselier int small_type<Dummy>::moved = 0;
1653461dbc0SEric Fiselier
1663461dbc0SEric Fiselier template <int Dummy>
1673461dbc0SEric Fiselier int small_type<Dummy>::const_copied = 0;
1683461dbc0SEric Fiselier
1693461dbc0SEric Fiselier template <int Dummy>
1703461dbc0SEric Fiselier int small_type<Dummy>::non_const_copied = 0;
1713461dbc0SEric Fiselier
1723461dbc0SEric Fiselier typedef small_type<> small;
1733461dbc0SEric Fiselier typedef small_type<1> small1;
1743461dbc0SEric Fiselier typedef small_type<2> small2;
1753461dbc0SEric Fiselier
1763461dbc0SEric Fiselier
1773461dbc0SEric Fiselier // A test type that will NOT trigger the small object optimization in any.
1783461dbc0SEric Fiselier template <int Dummy = 0>
1793461dbc0SEric Fiselier struct large_type
1803461dbc0SEric Fiselier {
1813461dbc0SEric Fiselier static int count;
1823461dbc0SEric Fiselier static int copied;
1833461dbc0SEric Fiselier static int moved;
1843461dbc0SEric Fiselier static int const_copied;
1853461dbc0SEric Fiselier static int non_const_copied;
1863461dbc0SEric Fiselier
resetlarge_type1873461dbc0SEric Fiselier static void reset() {
1883461dbc0SEric Fiselier large_type::copied = 0;
1893461dbc0SEric Fiselier large_type::moved = 0;
1903461dbc0SEric Fiselier large_type::const_copied = 0;
1913461dbc0SEric Fiselier large_type::non_const_copied = 0;
1923461dbc0SEric Fiselier }
1933461dbc0SEric Fiselier
1943461dbc0SEric Fiselier int value;
1953461dbc0SEric Fiselier
valuelarge_type196324506b9SEric Fiselier large_type(int val = 0) : value(val) {
1973461dbc0SEric Fiselier ++count;
1983461dbc0SEric Fiselier data[0] = 0;
1993461dbc0SEric Fiselier }
large_typelarge_type200324506b9SEric Fiselier large_type(int, int val, int) : value(val) {
201324506b9SEric Fiselier ++count;
202324506b9SEric Fiselier data[0] = 0;
203324506b9SEric Fiselier }
large_typelarge_type204324506b9SEric Fiselier large_type(std::initializer_list<int> il) : value(*il.begin()) {
205324506b9SEric Fiselier ++count;
206324506b9SEric Fiselier }
large_typelarge_type2073461dbc0SEric Fiselier large_type(large_type const & other) {
2083461dbc0SEric Fiselier value = other.value;
2093461dbc0SEric Fiselier ++count;
2103461dbc0SEric Fiselier ++copied;
2113461dbc0SEric Fiselier ++const_copied;
2123461dbc0SEric Fiselier }
2133461dbc0SEric Fiselier
large_typelarge_type2143461dbc0SEric Fiselier large_type(large_type & other) {
2153461dbc0SEric Fiselier value = other.value;
2163461dbc0SEric Fiselier ++count;
2173461dbc0SEric Fiselier ++copied;
2183461dbc0SEric Fiselier ++non_const_copied;
2193461dbc0SEric Fiselier }
2203461dbc0SEric Fiselier
large_typelarge_type2213461dbc0SEric Fiselier large_type(large_type && other) {
2223461dbc0SEric Fiselier value = other.value;
2233461dbc0SEric Fiselier other.value = 0;
2243461dbc0SEric Fiselier ++count;
2253461dbc0SEric Fiselier ++moved;
2263461dbc0SEric Fiselier }
2273461dbc0SEric Fiselier
~large_typelarge_type2283461dbc0SEric Fiselier ~large_type() {
2293461dbc0SEric Fiselier value = 0;
2303461dbc0SEric Fiselier --count;
2313461dbc0SEric Fiselier }
2323461dbc0SEric Fiselier
2333461dbc0SEric Fiselier private:
2343461dbc0SEric Fiselier large_type& operator=(large_type const&) = delete;
2353461dbc0SEric Fiselier large_type& operator=(large_type &&) = delete;
2363461dbc0SEric Fiselier int data[10];
2373461dbc0SEric Fiselier };
2383461dbc0SEric Fiselier
2393461dbc0SEric Fiselier template <int Dummy>
2403461dbc0SEric Fiselier int large_type<Dummy>::count = 0;
2413461dbc0SEric Fiselier
2423461dbc0SEric Fiselier template <int Dummy>
2433461dbc0SEric Fiselier int large_type<Dummy>::copied = 0;
2443461dbc0SEric Fiselier
2453461dbc0SEric Fiselier template <int Dummy>
2463461dbc0SEric Fiselier int large_type<Dummy>::moved = 0;
2473461dbc0SEric Fiselier
2483461dbc0SEric Fiselier template <int Dummy>
2493461dbc0SEric Fiselier int large_type<Dummy>::const_copied = 0;
2503461dbc0SEric Fiselier
2513461dbc0SEric Fiselier template <int Dummy>
2523461dbc0SEric Fiselier int large_type<Dummy>::non_const_copied = 0;
2533461dbc0SEric Fiselier
2543461dbc0SEric Fiselier typedef large_type<> large;
2553461dbc0SEric Fiselier typedef large_type<1> large1;
2563461dbc0SEric Fiselier typedef large_type<2> large2;
2573461dbc0SEric Fiselier
2583461dbc0SEric Fiselier // The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy'
2593461dbc0SEric Fiselier // and 'throws_on_move'.
2603461dbc0SEric Fiselier struct my_any_exception {};
2613461dbc0SEric Fiselier
throwMyAnyExpression()2623461dbc0SEric Fiselier void throwMyAnyExpression() {
2633461dbc0SEric Fiselier #if !defined(TEST_HAS_NO_EXCEPTIONS)
2643461dbc0SEric Fiselier throw my_any_exception();
2653461dbc0SEric Fiselier #else
2663461dbc0SEric Fiselier assert(false && "Exceptions are disabled");
2673461dbc0SEric Fiselier #endif
2683461dbc0SEric Fiselier }
2693461dbc0SEric Fiselier
2703461dbc0SEric Fiselier // A test type that will trigger the small object optimization within 'any'.
2713461dbc0SEric Fiselier // this type throws if it is copied.
2723461dbc0SEric Fiselier struct small_throws_on_copy
2733461dbc0SEric Fiselier {
2743461dbc0SEric Fiselier static int count;
275324506b9SEric Fiselier static int copied;
276324506b9SEric Fiselier static int moved;
resetsmall_throws_on_copy277324506b9SEric Fiselier static void reset() { count = copied = moved = 0; }
2783461dbc0SEric Fiselier int value;
2793461dbc0SEric Fiselier
valuesmall_throws_on_copy2803461dbc0SEric Fiselier explicit small_throws_on_copy(int val = 0) : value(val) {
2813461dbc0SEric Fiselier ++count;
2823461dbc0SEric Fiselier }
small_throws_on_copysmall_throws_on_copy283324506b9SEric Fiselier explicit small_throws_on_copy(int, int val, int) : value(val) {
284324506b9SEric Fiselier ++count;
285324506b9SEric Fiselier }
small_throws_on_copysmall_throws_on_copy2863461dbc0SEric Fiselier small_throws_on_copy(small_throws_on_copy const &) {
2873461dbc0SEric Fiselier throwMyAnyExpression();
2883461dbc0SEric Fiselier }
2893461dbc0SEric Fiselier
throwsmall_throws_on_copy2903461dbc0SEric Fiselier small_throws_on_copy(small_throws_on_copy && other) throw() {
2913461dbc0SEric Fiselier value = other.value;
292324506b9SEric Fiselier ++count; ++moved;
2933461dbc0SEric Fiselier }
2943461dbc0SEric Fiselier
~small_throws_on_copysmall_throws_on_copy2953461dbc0SEric Fiselier ~small_throws_on_copy() {
2963461dbc0SEric Fiselier --count;
2973461dbc0SEric Fiselier }
2983461dbc0SEric Fiselier private:
2993461dbc0SEric Fiselier small_throws_on_copy& operator=(small_throws_on_copy const&) = delete;
3003461dbc0SEric Fiselier small_throws_on_copy& operator=(small_throws_on_copy &&) = delete;
3013461dbc0SEric Fiselier };
3023461dbc0SEric Fiselier
3033461dbc0SEric Fiselier int small_throws_on_copy::count = 0;
304324506b9SEric Fiselier int small_throws_on_copy::copied = 0;
305324506b9SEric Fiselier int small_throws_on_copy::moved = 0;
306324506b9SEric Fiselier
3073461dbc0SEric Fiselier
3083461dbc0SEric Fiselier // A test type that will NOT trigger the small object optimization within 'any'.
3093461dbc0SEric Fiselier // this type throws if it is copied.
3103461dbc0SEric Fiselier struct large_throws_on_copy
3113461dbc0SEric Fiselier {
3123461dbc0SEric Fiselier static int count;
313324506b9SEric Fiselier static int copied;
314324506b9SEric Fiselier static int moved;
resetlarge_throws_on_copy315324506b9SEric Fiselier static void reset() { count = copied = moved = 0; }
3163461dbc0SEric Fiselier int value = 0;
3173461dbc0SEric Fiselier
valuelarge_throws_on_copy3183461dbc0SEric Fiselier explicit large_throws_on_copy(int val = 0) : value(val) {
3193461dbc0SEric Fiselier data[0] = 0;
3203461dbc0SEric Fiselier ++count;
3213461dbc0SEric Fiselier }
large_throws_on_copylarge_throws_on_copy322324506b9SEric Fiselier explicit large_throws_on_copy(int, int val, int) : value(val) {
323324506b9SEric Fiselier data[0] = 0;
324324506b9SEric Fiselier ++count;
325324506b9SEric Fiselier }
large_throws_on_copylarge_throws_on_copy3263461dbc0SEric Fiselier large_throws_on_copy(large_throws_on_copy const &) {
3273461dbc0SEric Fiselier throwMyAnyExpression();
3283461dbc0SEric Fiselier }
3293461dbc0SEric Fiselier
throwlarge_throws_on_copy3303461dbc0SEric Fiselier large_throws_on_copy(large_throws_on_copy && other) throw() {
3313461dbc0SEric Fiselier value = other.value;
332324506b9SEric Fiselier ++count; ++moved;
3333461dbc0SEric Fiselier }
3343461dbc0SEric Fiselier
~large_throws_on_copylarge_throws_on_copy3353461dbc0SEric Fiselier ~large_throws_on_copy() {
3363461dbc0SEric Fiselier --count;
3373461dbc0SEric Fiselier }
3383461dbc0SEric Fiselier
3393461dbc0SEric Fiselier private:
3403461dbc0SEric Fiselier large_throws_on_copy& operator=(large_throws_on_copy const&) = delete;
3413461dbc0SEric Fiselier large_throws_on_copy& operator=(large_throws_on_copy &&) = delete;
3423461dbc0SEric Fiselier int data[10];
3433461dbc0SEric Fiselier };
3443461dbc0SEric Fiselier
3453461dbc0SEric Fiselier int large_throws_on_copy::count = 0;
346324506b9SEric Fiselier int large_throws_on_copy::copied = 0;
347324506b9SEric Fiselier int large_throws_on_copy::moved = 0;
3483461dbc0SEric Fiselier
3493461dbc0SEric Fiselier // A test type that throws when it is moved. This object will NOT trigger
3503461dbc0SEric Fiselier // the small object optimization in 'any'.
3513461dbc0SEric Fiselier struct throws_on_move
3523461dbc0SEric Fiselier {
3533461dbc0SEric Fiselier static int count;
354324506b9SEric Fiselier static int copied;
355324506b9SEric Fiselier static int moved;
resetthrows_on_move356324506b9SEric Fiselier static void reset() { count = copied = moved = 0; }
3573461dbc0SEric Fiselier int value;
3583461dbc0SEric Fiselier
valuethrows_on_move3593461dbc0SEric Fiselier explicit throws_on_move(int val = 0) : value(val) { ++count; }
throws_on_movethrows_on_move360324506b9SEric Fiselier explicit throws_on_move(int, int val, int) : value(val) { ++count; }
throws_on_movethrows_on_move3613461dbc0SEric Fiselier throws_on_move(throws_on_move const & other) {
3623461dbc0SEric Fiselier value = other.value;
363324506b9SEric Fiselier ++count; ++copied;
3643461dbc0SEric Fiselier }
3653461dbc0SEric Fiselier
throws_on_movethrows_on_move3663461dbc0SEric Fiselier throws_on_move(throws_on_move &&) {
3673461dbc0SEric Fiselier throwMyAnyExpression();
3683461dbc0SEric Fiselier }
3693461dbc0SEric Fiselier
~throws_on_movethrows_on_move3703461dbc0SEric Fiselier ~throws_on_move() {
3713461dbc0SEric Fiselier --count;
3723461dbc0SEric Fiselier }
3733461dbc0SEric Fiselier private:
3743461dbc0SEric Fiselier throws_on_move& operator=(throws_on_move const&) = delete;
3753461dbc0SEric Fiselier throws_on_move& operator=(throws_on_move &&) = delete;
3763461dbc0SEric Fiselier };
3773461dbc0SEric Fiselier
3783461dbc0SEric Fiselier int throws_on_move::count = 0;
379324506b9SEric Fiselier int throws_on_move::copied = 0;
380324506b9SEric Fiselier int throws_on_move::moved = 0;
381324506b9SEric Fiselier
382324506b9SEric Fiselier struct small_tracked_t {
small_tracked_tsmall_tracked_t383324506b9SEric Fiselier small_tracked_t()
384324506b9SEric Fiselier : arg_types(&makeArgumentID<>()) {}
small_tracked_tsmall_tracked_t385324506b9SEric Fiselier small_tracked_t(small_tracked_t const&) noexcept
386324506b9SEric Fiselier : arg_types(&makeArgumentID<small_tracked_t const&>()) {}
small_tracked_tsmall_tracked_t387324506b9SEric Fiselier small_tracked_t(small_tracked_t &&) noexcept
388324506b9SEric Fiselier : arg_types(&makeArgumentID<small_tracked_t &&>()) {}
389324506b9SEric Fiselier template <class ...Args>
small_tracked_tsmall_tracked_t390324506b9SEric Fiselier explicit small_tracked_t(Args&&...)
391324506b9SEric Fiselier : arg_types(&makeArgumentID<Args...>()) {}
392324506b9SEric Fiselier template <class ...Args>
small_tracked_tsmall_tracked_t393324506b9SEric Fiselier explicit small_tracked_t(std::initializer_list<int>, Args&&...)
394324506b9SEric Fiselier : arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}
395324506b9SEric Fiselier
396324506b9SEric Fiselier TypeID const* arg_types;
397324506b9SEric Fiselier };
398324506b9SEric Fiselier static_assert(IsSmallObject<small_tracked_t>::value, "must be small");
399324506b9SEric Fiselier
400324506b9SEric Fiselier struct large_tracked_t {
large_tracked_tlarge_tracked_t401324506b9SEric Fiselier large_tracked_t()
402324506b9SEric Fiselier : arg_types(&makeArgumentID<>()) { dummy[0] = 42; }
large_tracked_tlarge_tracked_t403324506b9SEric Fiselier large_tracked_t(large_tracked_t const&) noexcept
404324506b9SEric Fiselier : arg_types(&makeArgumentID<large_tracked_t const&>()) {}
large_tracked_tlarge_tracked_t405324506b9SEric Fiselier large_tracked_t(large_tracked_t &&) noexcept
406324506b9SEric Fiselier : arg_types(&makeArgumentID<large_tracked_t &&>()) {}
407324506b9SEric Fiselier template <class ...Args>
large_tracked_tlarge_tracked_t408324506b9SEric Fiselier explicit large_tracked_t(Args&&...)
409324506b9SEric Fiselier : arg_types(&makeArgumentID<Args...>()) {}
410324506b9SEric Fiselier template <class ...Args>
large_tracked_tlarge_tracked_t411324506b9SEric Fiselier explicit large_tracked_t(std::initializer_list<int>, Args&&...)
412324506b9SEric Fiselier : arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}
413324506b9SEric Fiselier
414324506b9SEric Fiselier TypeID const* arg_types;
415fcad66f1SCasey Carter int dummy[sizeof(std::any) / sizeof(int) + 1];
416324506b9SEric Fiselier };
417324506b9SEric Fiselier
418fcad66f1SCasey Carter static_assert(!IsSmallObject<large_tracked_t>::value, "must not be small");
419324506b9SEric Fiselier
420324506b9SEric Fiselier
421324506b9SEric Fiselier template <class Type, class ...Args>
assertArgsMatch(std::any const & a)422324506b9SEric Fiselier void assertArgsMatch(std::any const& a) {
423324506b9SEric Fiselier assert(a.has_value());
424324506b9SEric Fiselier assert(containsType<Type>(a));
425ef2cdfe3SLouis Dionne assert(std::any_cast<Type const &>(a).arg_types == &makeArgumentID<Args...>());
426324506b9SEric Fiselier };
4273461dbc0SEric Fiselier
4283461dbc0SEric Fiselier
4293461dbc0SEric Fiselier #endif
430