Any++
Loading...
Searching...
No Matches
anyxx.hpp
Go to the documentation of this file.
1#pragma once
2
9
10#include <cassert>
11#include <concepts>
12#include <cstddef>
13#include <cstring>
14#include <expected>
15#include <functional>
16#include <map>
17#include <memory>
18#include <optional>
19#include <ranges>
20#include <stdexcept>
21#include <string>
22#include <type_traits>
23#include <typeindex>
24#include <typeinfo>
25#include <utility>
26#include <variant>
27#include <vector>
28
29#if defined(__clang__)
30#pragma GCC diagnostic ignored "-Wcast-function-type-mismatch"
31#pragma GCC diagnostic ignored "-Wmicrosoft-template-shadow"
32#pragma GCC diagnostic ignored "-Wunused-local-typedef"
33#pragma GCC diagnostic ignored "-Wextra-semi"
34#endif
35#if defined(__GNUC__) and !defined(__clang__)
36#pragma GCC diagnostic ignored "-Wunknown-pragmas"
37#pragma GCC diagnostic ignored "-Wcast-function-type"
38#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
39#endif
40
41#if defined(_MSC_VER) // MSVC
42#define ANYXX_USE_EBO __declspec(empty_bases)
43#else
44#define ANYXX_USE_EBO
45#endif
46#if defined(_MSC_VER) && not defined(__clang__) // MSVC
47#define LIFETIMEBOUND [[msvc::lifetimebound]]
48#ifndef ANYXX_GODBOLT
49#include <CppCoreCheck/Warnings.h>
50#pragma warning(default : CPPCORECHECK_LIFETIME_WARNINGS) // Enable
51 // lifetimebound
52#else
53#endif
54#elif defined(__clang__) // Clang
55#define LIFETIMEBOUND [[clang::lifetimebound]]
56#else
57#define LIFETIMEBOUND
58#endif
59
60#if defined(_MSC_VER) && not defined(__clang__) // MSVC
61#define AYXFORCEDINLINE __forceinline
62#pragma warning(disable : 4714)
63#else
64#define AYXFORCEDINLINE inline __attribute__((always_inline))
65#endif
66
67// --------------------------------------------------------------------------------
68// any meta class, derived from this gem:
69// https://github.com/AlexCodesApps/dynamic_interface
70
71#define ANYXX_EXTRACT(...) ANYXX_EXTRACT __VA_ARGS__
72#define ANYXX_NOTHING_ANYXX_EXTRACT
73#define ANYXX_PASTE(x, ...) x##__VA_ARGS__
74#define ANYXX_EVALUATING_PASTE(x, ...) ANYXX_PASTE(x, __VA_ARGS__)
75#define ANYXX_UNPAREN(x) ANYXX_EVALUATING_PASTE(ANYXX_NOTHING_, ANYXX_EXTRACT x)
76// usage:
77static_assert(std::same_as<ANYXX_UNPAREN(int), int>);
78static_assert(std::same_as<ANYXX_UNPAREN((int)), int>);
79
80#define ANYXX_JACKET_RETURN(...) \
81 anyxx::jacket_return<ANYXX_UNPAREN(ANYXX_UNPAREN(__VA_ARGS__))>
82
83#define _detail_EXPAND(...) \
84 _detail_EXPAND4( \
85 _detail_EXPAND4(_detail_EXPAND4(_detail_EXPAND4(__VA_ARGS__))))
86#define _detail_EXPAND4(...) \
87 _detail_EXPAND3( \
88 _detail_EXPAND3(_detail_EXPAND3(_detail_EXPAND3(__VA_ARGS__))))
89#define _detail_EXPAND3(...) \
90 _detail_EXPAND2( \
91 _detail_EXPAND2(_detail_EXPAND2(_detail_EXPAND2(__VA_ARGS__))))
92#define _detail_EXPAND2(...) \
93 _detail_EXPAND1( \
94 _detail_EXPAND1(_detail_EXPAND1(_detail_EXPAND1(__VA_ARGS__))))
95#define _detail_EXPAND1(...) __VA_ARGS__
96
97#define _detail_EXPAND_(...) \
98 _detail_EXPAND_4( \
99 _detail_EXPAND_4(_detail_EXPAND_4(_detail_EXPAND_4(__VA_ARGS__))))
100#define _detail_EXPAND_4(...) \
101 _detail_EXPAND_3( \
102 _detail_EXPAND_3(_detail_EXPAND_3(_detail_EXPAND_3(__VA_ARGS__))))
103#define _detail_EXPAND_3(...) \
104 _detail_EXPAND_2( \
105 _detail_EXPAND_2(_detail_EXPAND_2(_detail_EXPAND_2(__VA_ARGS__))))
106#define _detail_EXPAND_2(...) \
107 _detail_EXPAND_1( \
108 _detail_EXPAND_1(_detail_EXPAND_1(_detail_EXPAND_1(__VA_ARGS__))))
109#define _detail_EXPAND_1(...) __VA_ARGS__
110#define _detail_PARENS ()
111#define _detail_APPLY(macro, args) macro args
112#define _detail_REMOVE_PARENS(l) _detail_APPLY(_detail_EXPAND_1, l)
113#define _detail_foreach_macro_h(macro, a, ...) \
114 macro(a) \
115 __VA_OPT__(_detail_foreach_macro_a _detail_PARENS(macro, __VA_ARGS__))
116#define _detail_foreach_macro_a() _detail_foreach_macro_h
117#define _detail_foreach_macro(macro, ...) \
118 _detail_EXPAND(_detail_foreach_macro_h(macro, __VA_ARGS__))
119#define _detail_map_macro_h(macro, a, ...) \
120 macro(a) __VA_OPT__(, _detail_map_macro_a _detail_PARENS(macro, __VA_ARGS__))
121#define _detail_map_macro(macro, ...) \
122 _detail_EXPAND(_detail_map_macro_h(macro, __VA_ARGS__))
123#define _detail_map_macro_a() _detail_map_macro_h
124#define _detail_CONCAT_H(a, b) a##b
125#define _detail_CONCAT(a, b) _detail_CONCAT_H(a, b)
126
127#define _detail_ANYXX_FORWARD_PARAM_LIST_H(b, c, f, ...) \
128 std::forward<decltype(c)>(c) \
129 __VA_OPT__(, _detail_ANYXX_FORWARD_PARAM_LIST_A _detail_PARENS( \
130 b, _detail_CONCAT(b, c), __VA_ARGS__))
131#define _detail_ANYXX_FORWARD_PARAM_LIST_A() _detail_ANYXX_FORWARD_PARAM_LIST_H
132#define _detail_ANYXX_FORWARD_PARAM_LIST(...) \
133 _detail_EXPAND_(_detail_ANYXX_FORWARD_PARAM_LIST_H(__VA_ARGS__))
134
135#define _detail_ANYXX_CONCEPT_ARG_LIST_H(b, c, f, ...) \
136 c __VA_OPT__(, _detail_ANYXX_FORWARD_PARAM_LIST_A _detail_PARENS( \
137 b, _detail_CONCAT(b, c), __VA_ARGS__))
138#define _detail_ANYXX_FORWARD_PARAM_LIST_A() _detail_ANYXX_FORWARD_PARAM_LIST_H
139#define _detail_ANYXX_FORWARD_PARAM_LIST(...) \
140 _detail_EXPAND_(_detail_ANYXX_FORWARD_PARAM_LIST_H(__VA_ARGS__))
141
142#define _detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP_H(b, c, param_type, ...) \
143 anyxx::v_table_to_map<Concrete, ANYXX_UNPAREN(param_type)>:: \
144 template forward<decltype(c)>(std::forward<decltype(c)>(c)) __VA_OPT__( \
145 , _detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP_A _detail_PARENS( \
146 b, _detail_CONCAT(b, c), __VA_ARGS__))
147#define _detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP_A() \
148 _detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP_H
149#define _detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP(...) \
150 _detail_EXPAND_(_detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP_H(__VA_ARGS__))
151
152#define _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP_H(b, c, param_type, \
153 ...) \
154 anyxx::forward_trait_to_map<traited_t, ANYXX_UNPAREN(param_type)>:: \
155 template forward<decltype(c)>(std::forward<decltype(c)>(c)) __VA_OPT__( \
156 , _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP_A _detail_PARENS( \
157 b, _detail_CONCAT(b, c), __VA_ARGS__))
158#define _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP_A() \
159 _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP_H
160#define _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP(...) \
161 _detail_EXPAND_(_detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP_H(__VA_ARGS__))
162
163#define _detail_ANYXX_JACKET_PARAM_LIST_H(b, c, param_type, ...) \
164 [[maybe_unused]] auto&& c __VA_OPT__( \
165 , _detail_ANYXX_JACKET_PARAM_LIST_A _detail_PARENS( \
166 b, _detail_CONCAT(b, c), __VA_ARGS__))
167#define _detail_ANYXX_JACKET_PARAM_LIST_A() _detail_ANYXX_JACKET_PARAM_LIST_H
168#define _detail_ANYXX_JACKET_PARAM_LIST(...) \
169 _detail_EXPAND_(_detail_ANYXX_JACKET_PARAM_LIST_H(__VA_ARGS__))
170#define _detail_EXPAND_LIST(...) __VA_ARGS__
171
172#define _detail_ANYXX_V_TABLE_PARAM_LIST_H(b, c, param_type, ...) \
173 [[maybe_unused]] anyxx::v_table_param<any_value_t, \
174 ANYXX_UNPAREN(param_type)> c \
175 __VA_OPT__(, _detail_ANYXX_V_TABLE_PARAM_LIST_A _detail_PARENS( \
176 b, _detail_CONCAT(b, c), __VA_ARGS__))
177#define _detail_ANYXX_V_TABLE_PARAM_LIST_A() _detail_ANYXX_V_TABLE_PARAM_LIST_H
178#define _detail_ANYXX_V_TABLE_PARAM_LIST(...) \
179 _detail_EXPAND_(_detail_ANYXX_V_TABLE_PARAM_LIST_H(__VA_ARGS__))
180
181#define _detail_ANYXX_MAP_PARAM_LIST_H(b, c, param_type, ...) \
182 [[maybe_unused]] auto&& c __VA_OPT__( \
183 , _detail_ANYXX_MAP_PARAM_LIST_A _detail_PARENS(b, _detail_CONCAT(b, c), \
184 __VA_ARGS__))
185#define _detail_ANYXX_MAP_PARAM_LIST_A() _detail_ANYXX_MAP_PARAM_LIST_H
186#define _detail_ANYXX_MAP_PARAM_LIST(...) \
187 _detail_EXPAND_(_detail_ANYXX_MAP_PARAM_LIST_H(__VA_ARGS__))
188
189#define _detail_ANYXX_CONCEPT_PARAM_LIST_H(b, c, param_type, ...) \
190 [[maybe_unused]] anyxx::concept_arg<T, ANYXX_UNPAREN(param_type)> c \
191 __VA_OPT__(, _detail_ANYXX_CONCEPT_PARAM_LIST_A _detail_PARENS( \
192 b, _detail_CONCAT(b, c), __VA_ARGS__))
193#define _detail_ANYXX_CONCEPT_PARAM_LIST_A() _detail_ANYXX_CONCEPT_PARAM_LIST_H
194#define _detail_ANYXX_CONCEPT_PARAM_LIST(...) \
195 _detail_EXPAND_(_detail_ANYXX_CONCEPT_PARAM_LIST_H(__VA_ARGS__))
196
197#define _detail_ANYXX_EXACT_PARAM_LIST_H(b, c, param_type, ...) \
198 [[maybe_unused]] ANYXX_UNPAREN(param_type) c __VA_OPT__( \
199 , _detail_ANYXX_EXACT_PARAM_LIST_A _detail_PARENS( \
200 b, _detail_CONCAT(b, c), __VA_ARGS__))
201#define _detail_ANYXX_EXACT_PARAM_LIST_A() _detail_ANYXX_EXACT_PARAM_LIST_H
202#define _detail_ANYXX_EXACT_PARAM_LIST(...) \
203 _detail_EXPAND_(_detail_ANYXX_EXACT_PARAM_LIST_H(__VA_ARGS__))
204
205#define _detail_ANYXX_TYPENAME_PARAM_H(t) _detail_ANYXX_TYPENAME_PARAM t
206#define _detail_ANYXX_TYPENAME_PARAM(t) , typename t
207#define _detail_ANYXX_TYPENAME_PARAM_LIST(head, ...) \
208 typename _detail_REMOVE_PARENS(head) __VA_OPT__( \
209 _detail_foreach_macro(_detail_ANYXX_TYPENAME_PARAM_H, __VA_ARGS__))
210
211#define _detail_ANYXX_DUMMY_INT_PARAM_LIST_H(b, c, param_type, ...) \
212 int __VA_OPT__(, _detail_ANYXX_DUMMY_INT_PARAM_LIST_A _detail_PARENS( \
213 b, _detail_CONCAT(b, c), __VA_ARGS__))
214#define _detail_ANYXX_DUMMY_INT_PARAM_LIST_A() \
215 _detail_ANYXX_DUMMY_INT_PARAM_LIST_H
216#define _detail_ANYXX_DUMMY_INT_PARAM_LIST(...) \
217 __VA_OPT__( \
218 <_detail_ANYXX_DUMMY_INT_PARAM_LIST_H(dummy1, dummy2, __VA_ARGS__)>)
219
220#define _detail_ANYXX_OPTIONAL_TEMPLATE(...) __VA_OPT__(template)
221
222#define _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST(...) \
223 __VA_OPT__(template <_detail_ANYXX_TYPENAME_PARAM_LIST(__VA_ARGS__)>)
224#define _detail_ANYXX_OPTIONAL_MORE_TYPENAMES_PARAM_LIST(...) \
225 __VA_OPT__(, _detail_ANYXX_TYPENAME_PARAM_LIST(__VA_ARGS__))
226
227#define _detail_ANYXX_TEMPLATE_ARG_H(t) _detail_ANYXX_TEMPLATE_ARG t
228#define _detail_ANYXX_TEMPLATE_ARG(t) , t
229#define _detail_ANYXX_TEMPLATE_ARGS1(head, ...) \
230 _detail_REMOVE_PARENS(head) __VA_OPT__( \
231 _detail_foreach_macro(_detail_ANYXX_TEMPLATE_ARG_H, __VA_ARGS__))
232#define _detail_ANYXX_TEMPLATE_ARGS(...) \
233 __VA_OPT__(_detail_ANYXX_TEMPLATE_ARGS1(__VA_ARGS__))
234#define _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(...) \
235 __VA_OPT__(<_detail_ANYXX_TEMPLATE_ARGS(__VA_ARGS__)>)
236
237#define _detail_ANYXX_V_TABLE_TEMPLATE_FORMAL_ARGS_H(...) \
238 __VA_OPT__(<_detail_ANYXX_TEMPLATE_ARGS(__VA_ARGS__), anyxx::dyn>)
239#define _detail_ANYXX_V_TABLE_TEMPLATE_FORMAL_ARGS(t) \
240 _detail_ANYXX_V_TABLE_TEMPLATE_FORMAL_ARGS_H t
241
242#define _detail_LEAD_COMMA_H(...) __VA_OPT__(, )
243#define _detail_ANYXX_FPD_H(l) _detail_ANYXX_FUNCTION_PTR_DECL l
244#define _detail_ANYXX_MEMEBER_LIMP_H(l) _detail_ANYXX_LAMBDA_TO_MEMEBER_IMPL l
245
246#define _detail_LEAD_COMMA_H_E(l) _detail_LEAD_COMMA_H l
247
248#define __detail_ANYXX_ADD_HEAD(h, ...) h __VA_OPT__(, ) __VA_ARGS__
249#define __detail_ANYXX_ADD_HEAD_LIST(l, ...) \
250 __detail_ANYXX_ADD_HEAD(_detail_REMOVE_PARENS(l), __VA_ARGS__)
251// Examples:
252// __detail_ANYXX_ADD_HEAD(H, A, B, C, D) -> H, A, B, C, D
253// __detail_ANYXX_ADD_HEAD((H), (A), (B), (C), (D)) -> (H), (A), (B), (C), (D)
254// __detail_ANYXX_ADD_HEAD_LIST(((H1),(H2)), (A), (B), (C), (D))
255// -> (H1), (H2), (A), (B), (C), (D)
256
257#define __detail_ANYXX_ADD_TAIL(t, ...) __VA_ARGS__ __VA_OPT__(, ) t
258// Examples:
259// __detail_ANYXX_ADD_TAIL(T, A, B, C, D) -> (A), (B), (C), (D), (T)
260// __detail_ANYXX_ADD_TAIL(T, A, B, C, D) -> (A), (B), (C), (D), (T)
261
262#define _typename _typename1
263#define _typename1(t) t
264
265#define _detail_ANYXX_TEMPLATE_FORMAL_ARG_H(l) \
266 _detail_ANYXX_TEMPLATE_FORMAL_ARG l
267#define _detail_ANYXX_TEMPLATE_FORMAL_ARG(_typename) , typename _typename
268#define _detail_ANYXX_TEMPLATE_FORMAL_ARGS(...) \
269 __VA_OPT__(_detail_ANYXX_TEMPLATE_FORMAL_ARGS1(__VA_ARGS__))
270#define _detail_ANYXX_TEMPLATE_FORMAL_ARGS1(h, ...) \
271 typename _typename h __VA_OPT__( \
272 _detail_ANYXX_TEMPLATE_FORMAL_ARGS2((__VA_ARGS__)))
273#define _detail_ANYXX_TEMPLATE_FORMAL_ARGS2(l) \
274 _detail_foreach_macro(_detail_ANYXX_TEMPLATE_FORMAL_ARG_H, \
275 _detail_EXPAND_LIST l)
276
277#define _detail_ANYXX_V_TABLE_TEMPLATE_HEADER_H(...) \
278 __VA_OPT__(template <_detail_ANYXX_TEMPLATE_FORMAL_ARGS(__VA_ARGS__)>)
279
280#define _detail_ANYXX_V_TABLE_TEMPLATE_HEADER(t) \
281 _detail_ANYXX_V_TABLE_TEMPLATE_HEADER_H t
282
283#define _detail_ANYXX_INVOKE_TEMPLATE_PARAMS_H(...) __VA_OPT__(<__VA_ARGS__>)
284
285#define _detail_ANYXX_INVOKE_TEMPLATE_PARAMS(t) \
286 _detail_ANYXX_INVOKE_TEMPLATE_PARAMS_H t
287
288#define _detail_ANYXX_EXPAND_WITH_LEADING_COMMA(...) __VA_OPT__(, ) __VA_ARGS__
289
290#define _detail_ANYXX_OPTIONAL_TEMPLATE(...) __VA_OPT__(template)
291
292#define _detail_ANYXX_MAP_LIMP_H(l) _detail_ANYXX_MAP_IMPL l
293#define _detail_ANYXX_MAP_IMPL(access, overload, type, name, name_ext, \
294 exact_const, const_, trait_body, ...) \
295 access: \
296 static AYXFORCEDINLINE auto name([[maybe_unused]] T const_& x __VA_OPT__( \
297 , _detail_ANYXX_MAP_PARAM_LIST_H(a, _sig, __VA_ARGS__))) \
298 -> anyxx::map_return<T, ANYXX_UNPAREN(type)> { \
299 using namespace anyxx; \
300 return _detail_REMOVE_PARENS(trait_body)( \
301 __VA_OPT__(_detail_ANYXX_FORWARD_PARAM_LIST(a, _sig, __VA_ARGS__))); \
302 };
303
304#define _detail_ANYXX_CONCEPT_FN_H(l) _detail_ANYXX_CONCEPT_FN l
305#define _detail_ANYXX_CONCEPT_FN(access, overload, type, name, name_ext, \
306 exact_const, const_, trait_body, ...) \
307 requires requires( \
308 __VA_OPT__(_detail_ANYXX_CONCEPT_PARAM_LIST_H(a, sig_, __VA_ARGS__))) { \
309 { \
310 model_map.name(model __VA_OPT__( \
311 , _detail_ANYXX_CONCEPT_ARG_LIST_H(a, sig_, __VA_ARGS__))) \
312 } -> std::convertible_to<anyxx::map_return<T, ANYXX_UNPAREN(type)>>; \
313 };
314
315#define _detail_ANYXX_CONCEPT_STATIC_FN_H(l) _detail_ANYXX_CONCEPT_STATIC_FN l
316#define _detail_ANYXX_CONCEPT_STATIC_FN(template_params, return_type, name, \
317 body, ...) \
318 requires requires( \
319 __VA_OPT__(_detail_ANYXX_CONCEPT_PARAM_LIST_H(a, sig_, __VA_ARGS__))) { \
320 { \
321 model_map.name(trait_class __VA_OPT__( \
322 , _detail_ANYXX_CONCEPT_ARG_LIST_H(a, sig_, __VA_ARGS__))) \
323 } \
324 -> std::convertible_to<anyxx::map_return<T, ANYXX_UNPAREN(return_type)>>; \
325 };
326
327#define _detail_ANYXX_CONCEPT_TYPE_H(l) _detail_ANYXX_CONCEPT_TYPE l
328#define _detail_ANYXX_CONCEPT_TYPE(template_params, name, erased, default_) \
329 requires !std::same_as< \
330 typename decltype(model_map)::_detail_ANYXX_OPTIONAL_TEMPLATE( \
331 _detail_REMOVE_PARENS(template_params)) name \
332 _detail_ANYXX_DUMMY_INT_PARAM_LIST(ANYXX_UNPAREN(template_params)), \
333 anyxx::undefined>;
334
335//_detail_ANYXX_CONCEPT_TYPE_H((), value_type, anyxx::undefined,
336//(anyxx::undefined))
337
338#define _detail_ANYXX_MAP_STATIC_H(l) _detail_ANYXX_MAP_STATIC l
339#define _detail_ANYXX_MAP_STATIC(template_params, return_type, name, body, \
340 ...) \
341 public: \
342 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST( \
343 _detail_REMOVE_PARENS(template_params)) static AYXFORCEDINLINE auto \
344 name([[maybe_unused]] auto trait_class __VA_OPT__( \
345 , _detail_ANYXX_MAP_PARAM_LIST_H(a, _sig, __VA_ARGS__))) \
346 -> anyxx::map_return<T, ANYXX_UNPAREN(return_type)> { \
347 using namespace anyxx; \
348 return _detail_REMOVE_PARENS(body).template \
349 operator()<anyxx::use_as<T, typename decltype(trait_class)::trait_t>>( \
350 trait_class __VA_OPT__( \
351 , _detail_ANYXX_FORWARD_PARAM_LIST(a, _sig, __VA_ARGS__))); \
352 };
353
354//_detail_ANYXX_MAP_STATIC(((A), (B)), decltype(auto), forward,
355// ([](A&& a, B&& b) { return std::forward<A>(a); }),
356// A&&, B&&)
357// expands to ->
358// template <typename A, typename B>
359// static __forceinline decltype(auto)
360// forward([[maybe_unused]] A&& _sig, [[maybe_unused]] B&& a_sig) {
361// return [](A&& a, B&& b) {
362// return std::forward<A>(a);
363// }(std::forward<decltype(_sig)>(_sig), std::forward<decltype(a_sig)>(a_sig));
364//};
365
366#define _detail_ANYXX_JACKET_STATIC_H(l) _detail_ANYXX_JACKET_STATIC l
367#define _detail_ANYXX_JACKET_STATIC(template_params, return_type, name, body, \
368 ...) \
369 template <typename Self _detail_ANYXX_OPTIONAL_MORE_TYPENAMES_PARAM_LIST( \
370 _detail_REMOVE_PARENS(template_params))> \
371 AYXFORCEDINLINE decltype(auto) name( \
372 [[maybe_unused]] this Self&& self __VA_OPT__(, ) \
373 __VA_OPT__(_detail_ANYXX_JACKET_PARAM_LIST(a, _sig, __VA_ARGS__))) { \
374 using self_t = std::decay_t<Self>; \
375 static_assert(!self_t::dyn); \
376 using T = typename self_t::T; \
377 using proxy_t = typename self_t::proxy_t; \
378 using map_t = typename self_t::template static_dispatch_map_t<T>; \
379 using traited_t = typename proxy_t::value_t; \
380 using trait_t = typename self_t::trait_t; \
381 return ANYXX_JACKET_RETURN(return_type)::forward( \
382 map_t::_detail_ANYXX_OPTIONAL_TEMPLATE( \
383 _detail_REMOVE_PARENS(template_params)) \
384 name _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
385 _detail_REMOVE_PARENS(template_params))( \
386 anyxx::trait_class_<T, trait_t> __VA_OPT__( \
387 , _detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP( \
388 a, _sig, __VA_ARGS__))), \
389 std::forward<Self>(self)); \
390 };
391
392//_detail_ANYXX_JACKET_STATIC(((A), (B)), decltype(auto), forward,
393// ([](A&& a, B&& b) { return std::forward<A>(a); }),
394// A&&, B&&)
395// expands to ->
396//
397// template <typename Self, typename A, typename B>
398// __forceinline decltype(auto)
399// forward([[maybe_unused]] this Self const& self,
400// [[maybe_unused]] A&& _sig, [[maybe_unused]] B&& a_sig) {
401// static_assert(!Self::dyn);
402// using map_t = typename Self::static_dispatch_map_t;
403// return map_t::template forward<A, B>(std::forward<decltype(_sig)>(_sig),
404// std::forward<decltype(a_sig)>(a_sig));
405// };
406
407#define _detail_ANYXX_MAP_TYPE_H(l) _detail_ANYXX_MAP_TYPE l
408#define _detail_ANYXX_MAP_TYPE(template_params, name, erased, default_) \
409 public: \
410 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST(_detail_REMOVE_PARENS( \
411 template_params)) using name = _detail_REMOVE_PARENS(default_);
412
413//_detail_ANYXX_MAP_TYPE(((A), (B)), xyz, void, (std::map<A, B>))
414// ->
415// template <typename A, typename B>
416// using xyz = std::map<A, B>;
417
418#define _detail_ANYXX_JACKET_TYPE_H(l) _detail_ANYXX_JACKET_TYPE l
419#define _detail_ANYXX_JACKET_TYPE(template_params, name, erased, default_) \
420 template <typename Q _detail_ANYXX_OPTIONAL_MORE_TYPENAMES_PARAM_LIST( \
421 _detail_REMOVE_PARENS(template_params))> \
422 using name = std::conditional_t< \
423 std::same_as<void, Q>, erased, \
424 typename static_dispatch_map_t<Q>::_detail_ANYXX_OPTIONAL_TEMPLATE( \
425 _detail_REMOVE_PARENS(template_params)) \
426 name _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
427 _detail_REMOVE_PARENS(template_params))>;
428
429//_detail_ANYXX_JACKET_TYPE(((A),(B)), xyz, void, (std::map<A,B>))
430// ->
431// template <typename Self, typename A, typename B>
432// using xyz = std::conditional_t<
433// Self::dyn, void, typename Self::static_dispatch_map_t::template xyz<A,
434// B>>;
435
436#define _detail_ANYXX_MAP_VARIANT_LIMP_H(l) _detail_ANYXX_MAP_VARIANT_IMPL l
437#define _detail_ANYXX_MAP_VARIANT_IMPL(access, overload, type, name, name_ext, \
438 exact_const, const_, trait_body, ...) \
439 static AYXFORCEDINLINE auto name([[maybe_unused]] T const_& x __VA_OPT__( \
440 , _detail_ANYXX_MAP_PARAM_LIST_H(a, _sig, __VA_ARGS__))) \
441 -> decltype(auto) { \
442 return std::visit( \
443 anyxx::overloads{ \
444 [&]<typename V>(V&& v) { \
445 return x_model_map<std::decay_t<V>>::name( \
446 std::forward<V>(v) __VA_OPT__(, ) \
447 __VA_OPT__(_detail_ANYXX_FORWARD_PARAM_LIST( \
448 a, _sig, __VA_ARGS__))); \
449 }, \
450 [&]<anyxx::is_any Any>([[maybe_unused]] Any&& any) { \
451 return std::forward<Any>(any).name(__VA_OPT__( \
452 _detail_ANYXX_FORWARD_PARAM_LIST(a, _sig, __VA_ARGS__))); \
453 }}, \
454 x); \
455 };
456
457#define _detail_ANYXX_FUNCTION_PTR_DECL(access, overload, type, name, \
458 name_ext, exact_const, const_, \
459 map_body, ...) \
460 anyxx::v_table_return<any_value_t, ANYXX_UNPAREN(type)> (*name)( \
461 void const_* __VA_OPT__( \
462 , _detail_ANYXX_V_TABLE_PARAM_LIST(a, _sig, __VA_ARGS__)));
463
464#define _detail_ANYXX_LAMBDA_TO_MEMEBER_IMPL(access, overload, type, name, \
465 name_ext, exact_const, const_, \
466 map_body, ...) \
467 name = [](void const_* _vp __VA_OPT__( \
468 , _detail_ANYXX_V_TABLE_PARAM_LIST(a, _sig, __VA_ARGS__))) \
469 -> anyxx::v_table_return<any_value_t, ANYXX_UNPAREN(type)> { \
470 if constexpr (std::same_as<anyxx::self&, ANYXX_UNPAREN(type)>) { \
471 model_map{}.name( \
472 *anyxx::unchecked_unerase_cast<Concrete>(_vp) __VA_OPT__(, ) \
473 __VA_OPT__(_detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP( \
474 a, _sig, __VA_ARGS__))); \
475 return anyxx::handle_self_ref_return<ANYXX_UNPAREN(type)>{}(); \
476 } else { \
477 return model_map{}.name( \
478 *anyxx::unchecked_unerase_cast<Concrete>(_vp) __VA_OPT__(, ) \
479 __VA_OPT__(_detail_ANYXX_FORWARD_PARAM_LIST_TO_MAP( \
480 a, _sig, __VA_ARGS__))); \
481 } \
482 };
483
484#define _detail_ANYXX_FN_H(l) _detail_ANYXX_FN l
485#define _detail_ANYXX_FN(access, overload, type, name, name_ext, exact_const, \
486 const_, map_body, ...) \
487 overload template <typename Self> \
488 AYXFORCEDINLINE decltype(auto) name_ext(this Self&& self __VA_OPT__( \
489 , ) __VA_OPT__(_detail_ANYXX_JACKET_PARAM_LIST(a, _sig, __VA_ARGS__))) \
490 requires(::anyxx::const_correct_call_for_proxy_and_self< \
491 void const_*, typename std::decay_t<Self>::proxy_t, \
492 std::is_const_v<std::remove_reference_t<Self>>, exact_const>) \
493 { \
494 using self_t = std::decay_t<Self>; \
495 using T = typename self_t::T; \
496 using proxy_t = typename self_t::proxy_t; \
497 \
498 if constexpr (!self_t::dyn) { \
499 using traited_t = typename proxy_t::value_t; \
500 if constexpr (std::same_as<void, ANYXX_UNPAREN(type)>) { \
501 return static_dispatch_map_t<T>::name( \
502 get_proxy_value(self) __VA_OPT__(, ) \
503 __VA_OPT__(_detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP( \
504 a, _sig, __VA_ARGS__))); \
505 } else { \
506 return ANYXX_JACKET_RETURN(type)::forward( \
507 static_dispatch_map_t<T>::name( \
508 get_proxy_value(self) __VA_OPT__(, ) \
509 __VA_OPT__(_detail_ANYXX_FORWARD_JACKET_PARAM_LIST_TO_MAP( \
510 a, _sig, __VA_ARGS__))), \
511 std::forward<Self>(self)); \
512 } \
513 } else { \
514 if constexpr (std::same_as<void, ANYXX_UNPAREN(type)>) { \
515 return get_v_table(self)->name(anyxx::get_proxy_ptr(self) __VA_OPT__( \
516 , _detail_ANYXX_FORWARD_PARAM_LIST(a, _sig, __VA_ARGS__))); \
517 } else { \
518 return ANYXX_JACKET_RETURN(type)::forward( \
519 get_v_table(self)->name(anyxx::get_proxy_ptr(self) __VA_OPT__( \
520 , _detail_ANYXX_FORWARD_PARAM_LIST(a, _sig, __VA_ARGS__))), \
521 std::forward<Self>(self)); \
522 } \
523 } \
524 }
525
526#define _detail_ANYXX_CONCEPT_FUNCTIONS(...) \
527 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_CONCEPT_FN_H, \
528 _detail_EXPAND_LIST __VA_ARGS__))
529
530#define _detail_ANYXX_CONCEPT_STATIC_FUNCTIONS(...) \
531 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_CONCEPT_STATIC_FN_H, \
532 _detail_EXPAND_LIST __VA_ARGS__))
533
534#define _detail_ANYXX_CONCEPT_TYPES(...) \
535 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_CONCEPT_TYPE_H, \
536 _detail_EXPAND_LIST __VA_ARGS__))
537
538#define _detail_ANYXX_MAP_FUNCTIONS(...) \
539 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_MAP_LIMP_H, \
540 _detail_EXPAND_LIST __VA_ARGS__))
541
542#define _detail_ANYXX_MAP_STATIC_FUNCTIONS(...) \
543 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_MAP_STATIC_H, \
544 _detail_EXPAND_LIST __VA_ARGS__))
545
546#define _detail_ANYXX_MAP_TYPES(...) \
547 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_MAP_TYPE_H, \
548 _detail_EXPAND_LIST __VA_ARGS__))
549
550#define _detail_ANYXX_MAP_VARIANT_FUNCTIONS(...) \
551 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_MAP_VARIANT_LIMP_H, \
552 _detail_EXPAND_LIST __VA_ARGS__))
553
554#define _detail_ANYXX_V_TABLE_FUNCTION_PTRS(...) \
555 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_FPD_H, \
556 _detail_EXPAND_LIST __VA_ARGS__));
557
558#define _detail_ANYXX_V_TABLE_LAMBDAS(...) \
559 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_MEMEBER_LIMP_H, \
560 _detail_EXPAND_LIST __VA_ARGS__));
561
562#define _detail_ANYXX_FNS(...) \
563 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_FN_H, \
564 _detail_EXPAND_LIST __VA_ARGS__))
565
566#define _detail_ANYXX_JACKET_STATIC_FNS(...) \
567 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_JACKET_STATIC_H, \
568 _detail_EXPAND_LIST __VA_ARGS__))
569
570#define _detail_ANYXX_JACKET_TYPES(...) \
571 __VA_OPT__(_detail_foreach_macro(_detail_ANYXX_JACKET_TYPE_H, \
572 _detail_EXPAND_LIST __VA_ARGS__))
573
574#define _detail_ANYXX_MAKE_V_TABLE_FUNCTION_NAME(n) \
575 _detail_CONCAT(make_, _detail_CONCAT(n, _v_table))
576
577// cppcheck-suppress-macro performance-unnecessary-value-param
578#define TRAIT_META_FUNCTION( \
579 any_template_params, model_map_template_params, concrete_template_params, \
580 static_dispatch_template_params, variant_model_map_template_params, n, \
581 BASE, base_template_params, base_model_map_template_params, l, static_fns, \
582 typedefs, decoration) \
583 \
584 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST(any_template_params) struct n; \
585 \
586 template <_detail_ANYXX_TYPENAME_PARAM_LIST(model_map_template_params)> \
587 struct n##_default_model_map { \
588 using default_map = n##_default_model_map; \
589 _detail_ANYXX_MAP_FUNCTIONS(l); \
590 _detail_ANYXX_MAP_STATIC_FUNCTIONS(static_fns); \
591 _detail_ANYXX_MAP_TYPES(typedefs); \
592 }; \
593 template <_detail_ANYXX_TYPENAME_PARAM_LIST(model_map_template_params)> \
594 struct n##_model_map : n##_default_model_map<_detail_ANYXX_TEMPLATE_ARGS( \
595 model_map_template_params)> {}; \
596 \
597 template <_detail_ANYXX_TYPENAME_PARAM_LIST(model_map_template_params)> \
598 requires(anyxx::is_variant<T>) \
599 struct n## \
600 _model_map<_detail_ANYXX_TEMPLATE_ARGS(model_map_template_params)> { \
601 template <typename V> \
602 using x_model_map = n##_model_map<_detail_ANYXX_TEMPLATE_ARGS( \
603 variant_model_map_template_params)>; \
604 _detail_ANYXX_MAP_VARIANT_FUNCTIONS(l) \
605 }; \
606 \
607 struct n##_has_open_dispatch; \
608 \
609 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST( \
610 any_template_params) struct n##_v_table \
611 : BASE \
612 _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(base_template_params)::v_table_t, \
613 anyxx::dispatch_holder<anyxx::is_type_complete<n##_has_open_dispatch>, \
614 n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
615 any_template_params)> { \
616 using v_table_base_t = typename BASE _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
617 base_template_params)::v_table_t; \
618 \
619 using v_table_t = n##_v_table; \
620 \
621 using any_value_t = \
622 anyxx::any<anyxx::val, n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
623 any_template_params)>; \
624 \
625 static constexpr bool open_dispatch_enabeled = \
626 anyxx::is_type_complete<n##_has_open_dispatch>; \
627 using own_dispatch_holder_t = typename anyxx::dispatch_holder< \
628 open_dispatch_enabeled, \
629 n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(any_template_params)>; \
630 \
631 static bool static_is_derived_from(const std::type_info& from) { \
632 if constexpr (std::derived_from<v_table_base_t, \
633 anyxx::observeable_rtti_v_table>) { \
634 return typeid(v_table_t) == from \
635 ? true \
636 : v_table_base_t::static_is_derived_from(from); \
637 } else { \
638 return false; \
639 } \
640 } \
641 \
642 using T = void; \
643 \
644 _detail_ANYXX_V_TABLE_FUNCTION_PTRS(l); \
645 \
646 template <typename Concrete> \
647 explicit(false) n##_v_table(std::in_place_type_t<Concrete> concrete); \
648 }; \
649 \
650 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST(any_template_params) struct n \
651 : BASE \
652 _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(base_template_params) { \
653 using any_value_t = \
654 anyxx::any<anyxx::val, n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
655 any_template_params)>; \
656 \
657 using base_t = \
658 BASE _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(base_template_params); \
659 \
660 using v_table_base_t = base_t::v_table_t; \
661 using v_table_t = \
662 n##_v_table _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(any_template_params); \
663 template <typename StaticDispatchType> \
664 using static_dispatch_map_t = n##_model_map<_detail_ANYXX_TEMPLATE_ARGS( \
665 static_dispatch_template_params)>; \
666 \
667 template <typename M> \
668 constexpr static bool modeled_by(); \
669 \
670 _detail_ANYXX_FNS(l); \
671 _detail_ANYXX_JACKET_STATIC_FNS(static_fns); \
672 _detail_ANYXX_JACKET_TYPES(typedefs); \
673 _detail_REMOVE_PARENS(decoration); \
674 }; \
675 \
676 template <_detail_ANYXX_TYPENAME_PARAM_LIST(model_map_template_params)> \
677 concept _detail_CONCAT(_detail_CONCAT(is_, n), _model) = \
678 requires( \
679 T model, \
680 anyxx::any_trait_class<T, n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
681 any_template_params)> \
682 trait_class, \
683 n##_model_map<_detail_ANYXX_TEMPLATE_ARGS( \
684 model_map_template_params)> \
685 model_map) { \
686 requires anyxx::is_type_complete<T>; \
687 _detail_ANYXX_CONCEPT_FUNCTIONS(l) \
688 _detail_ANYXX_CONCEPT_STATIC_FUNCTIONS(static_fns) \
689 _detail_ANYXX_CONCEPT_TYPES(typedefs) \
690 } && \
691 BASE _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
692 base_template_params)::template modeled_by<T>(); \
693 \
694 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST( \
695 any_template_params) template <typename T> \
696 constexpr bool n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
697 any_template_params)::modeled_by() { \
698 return _detail_CONCAT( \
699 _detail_CONCAT(is_, n), \
700 _model)<_detail_ANYXX_TEMPLATE_ARGS(model_map_template_params)>; \
701 }; \
702 \
703 _detail_ANYXX_OPTIONAL_TYPENAME_PARAM_LIST( \
704 any_template_params) template <typename Concrete> \
705 n##_v_table \
706 _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(any_template_params)::n##_v_table( \
707 std::in_place_type_t<Concrete> concrete) \
708 : v_table_base_t(concrete) { \
709 using model_map = \
710 n##_model_map<_detail_ANYXX_TEMPLATE_ARGS(concrete_template_params)>; \
711 \
712 _detail_ANYXX_V_TABLE_LAMBDAS(l); \
713 \
714 if constexpr (open_dispatch_enabeled) { \
715 own_dispatch_holder_t::set_dispatch_table( \
716 ::anyxx::dispatch_table_instance<n##_v_table, Concrete>()); \
717 } \
718 \
719 ::anyxx::set_is_derived_from<v_table_t>(this); \
720 };
721
722#define __detail_ANYXX_TRAIT_(t, n, BASE, l, static_fns, typedefs, decoration) \
723 TRAIT_META_FUNCTION(, (T), (Concrete), (StaticDispatchType), (V), n, BASE, , \
724 (T), l, static_fns, typedefs, decoration)
725
750
756#define TRAIT_EX_(n, BASE, l, static_fns, typedefs, decoration) \
757 __detail_ANYXX_TRAIT_(, n, BASE, l, static_fns, typedefs, decoration)
758
762#define TRAIT_(n, BASE, l) TRAIT_EX_(n, BASE, l, , , ())
763
774#define TRAIT(n, fns) TRAIT_(n, anyxx::base_trait, fns)
775
782#define TRAIT_EX(n, ...) TRAIT_EX_(n, anyxx::base_trait, __VA_ARGS__)
783
790#define TRAIT_TEMPLATE_EX_(t, n, base, base_template_types, l, static_fns, \
791 typedefs, decoration) \
792 TRAIT_META_FUNCTION( \
793 _detail_REMOVE_PARENS(t), \
794 __detail_ANYXX_ADD_HEAD((T), _detail_REMOVE_PARENS(t)), \
795 __detail_ANYXX_ADD_HEAD((Concrete), _detail_REMOVE_PARENS(t)), \
796 __detail_ANYXX_ADD_HEAD((StaticDispatchType), _detail_REMOVE_PARENS(t)), \
797 __detail_ANYXX_ADD_HEAD((V), _detail_REMOVE_PARENS(t)), n, base, \
798 _detail_REMOVE_PARENS(base_template_types), \
799 __detail_ANYXX_ADD_HEAD((T), \
800 _detail_REMOVE_PARENS(base_template_types)), \
801 l, static_fns, typedefs, decoration)
802
806#define TRAIT_TEMPLATE_EX(t, n, l, static_fns, typedefs, decoration) \
807 TRAIT_TEMPLATE_EX_(t, n, anyxx::base_trait, (), l, static_fns, typedefs, \
808 decoration)
809
813#define TRAIT_TEMPLATE_(t, n, base, base_template_types, l) \
814 TRAIT_TEMPLATE_EX_(t, n, base, base_template_types, l, , , ())
815
819#define TRAIT_TEMPLATE(t, n, l) TRAIT_TEMPLATE_(t, n, anyxx::base_trait, (), l)
820
822// cppcheck-suppress-macro performance-unnecessary-value-param
823#define ANY_META_FUNCTION(pure_template_params, \
824 any_template_params_with_defaults, n) \
825 \
826 template <_detail_ANYXX_TYPENAME_PARAM_LIST( \
827 any_template_params_with_defaults)> \
828 using any_##n = anyxx::any<Proxy, n _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS( \
829 pure_template_params)>;
830
832
833#define __detail_ANYXX_ANY_CMF(t, t_with_defaults, n) \
834 ANY_META_FUNCTION(, _detail_REMOVE_PARENS(t_with_defaults), n)
835
836#define __detail_ANYXX_ANY_EX_(n, proxy_default) \
837 __detail_ANYXX_ANY_CMF( \
838 ((Proxy)), ((Proxy = anyxx::default_proxy<proxy_default>::type)), n)
839
843#define ANY_EX_(n, BASE, l, proxy_default, decoration) \
844 TRAIT_EX_(n, BASE, l, decoration) \
845 __detail_ANYXX_ANY_EX_(n, proxy_default)
846
850#define ANY_EX(n, l, proxy_default, decoration) \
851 TRAIT_EX(n, l, decoration) \
852 __detail_ANYXX_ANY_EX_(n, proxy_default)
853
857#define ANY_(n, BASE, l, proxy_default) \
858 TRAIT_(n, BASE, l) \
859 __detail_ANYXX_ANY_EX_(n, proxy_default)
860
884#define ANY(n, l, ...) \
885 TRAIT(n, l) \
886 __detail_ANYXX_ANY_EX_(n, __VA_ARGS__)
887
888#define __detail_ANYXX_ANY_TEMPLATE_CMF(t, n, proxy_default) \
889 ANY_META_FUNCTION(_detail_REMOVE_PARENS(t), \
890 __detail_ANYXX_ADD_TAIL( \
891 (Proxy = anyxx::default_proxy<proxy_default>::type), \
892 _detail_REMOVE_PARENS(t)), \
893 n)
894
899#define ANY_TEMPLATE_EX_(t, n, BASE, bt, l, proxy_default, decoration) \
900 TRAIT_TEMPLATE_EX_(t, n, BASE, bt, l, decoration) \
901 __detail_ANYXX_ANY_TEMPLATE_CMF(t, n, proxy_default)
902
907#define ANY_TEMPLATE_(t, n, BASE, bt, l, proxy_default) \
908 TRAIT_TEMPLATE_(t, n, BASE, bt, l) \
909 __detail_ANYXX_ANY_TEMPLATE_CMF(t, n, proxy_default)
910
915#define ANY_TEMPLATE(t, n, l, proxy_default) \
916 TRAIT_TEMPLATE(t, n, l) \
917 __detail_ANYXX_ANY_TEMPLATE_CMF(t, n, proxy_default)
918
923#define ANY_TEMPLATE_EX(t, n, l, proxy_default, static_fns, typedefs, \
924 decoration) \
925 TRAIT_TEMPLATE_EX(t, n, l, static_fns, typedefs, decoration) \
926 __detail_ANYXX_ANY_TEMPLATE_CMF(t, n, proxy_default)
927
929
930#define ANY_FN_(...) (__VA_ARGS__)
931#define ANY_OVERLOAD(name) using base_t::name;
932
933#define __detail_ANYXX_MEMBER_FN(access, overload, ret, name, name_ext, \
934 exact_const, const_, params) \
935 ANY_FN_(access, overload, ret, name, name_ext, exact_const, const_, \
936 (x.name_ext), _detail_EXPAND params)
937
978
982#define ANY_FN_PURE(ret, name, params, const_) \
983 ANY_FN_(private, , ret, name, name, false, const_, \
984 (_detail_ANYXX_TRAIT_ERROR_MESSAGE(name, ret)), \
985 _detail_EXPAND params)
986
990#define ANY_FN_PURE_EXACT(ret, name, params, const_) \
991 ANY_FN_(private, , ret, name, name, true, const_, \
992 (_detail_ANYXX_TRAIT_ERROR_MESSAGE(name, ret)), \
993 _detail_EXPAND params)
994
998#define ANY_FN_DEF(access, ret, name, params, const_, ...) \
999 ANY_FN_(access, , ret, name, name, false, const_, (__VA_ARGS__), \
1000 _detail_EXPAND params)
1001
1004#define ANY_FN_DEF_EXACT(access, ret, name, params, const_, ...) \
1005 ANY_FN_(access, , ret, name, name, true, const_, (__VA_ARGS__), \
1006 _detail_EXPAND params)
1007
1019#define ANY_FN(ret, name, params, const_) \
1020 __detail_ANYXX_MEMBER_FN(public, , ret, name, name, false, const_, params)
1021
1026#define ANY_FN_EXACT(ret, name, params, const_) \
1027 __detail_ANYXX_MEMBER_FN(public, , ret, name, name, true, const_, params)
1028
1034#define ANY_FN_OVERLOAD(ret, name, params, const_) \
1035 __detail_ANYXX_MEMBER_FN(public, ANY_OVERLOAD(name), ret, name, name, false, \
1036 const_, params)
1037
1043#define ANY_FN_OVERLOAD_EXACT(ret, name, params, const_) \
1044 __detail_ANYXX_MEMBER_FN(public, ANY_OVERLOAD(name), ret, name, name, true, \
1045 const_, params)
1046
1052#define ANY_OP_MAP_NAMED(ret, op, name, params, const_) \
1053 __detail_ANYXX_MEMBER_FN(public, , ret, name, operator op, false, const_, \
1054 params)
1055
1059#define ANY_OP(ret, op, params, const_) \
1060 ANY_OP_MAP_NAMED(ret, op, _detail_CONCAT(__op__, __COUNTER__), params, const_)
1061
1066#define ANY_OP_DEF(access, ret, op, name, params, const_, ...) \
1067 ANY_FN_(access, , ret, name, operator op, false, const_, (__VA_ARGS__), \
1068 _detail_EXPAND params)
1069
1070#define ANY_OP_EXACT_MAP_NAMED(ret, op, name, params, const_) \
1071 __detail_ANYXX_MEMBER_FN(public, , ret, name, operator op, true, const_, \
1072 params)
1073
1078#define ANY_OP_EXACT(ret, op, params, const_) \
1079 ANY_OP_EXACT_MAP_NAMED(ret, op, _detail_CONCAT(__op__, __COUNTER__), params, \
1080 const_)
1081
1087#define ANY_OP_EXACT_DEF(access, ret, op, name, params, const_, ...) \
1088 ANY_FN_(access, , ret, name, operator op, true, const_, (__VA_ARGS__), \
1089 _detail_EXPAND params)
1090
1096#define ANY_OP_EXACT_OVERLOAD_MAP_NAMED(ret, op, name, params, const_) \
1097 __detail_ANYXX_MEMBER_FN(ANY_OVERLOAD(operator op), ret, name, operator op, \
1098 true, const_, params)
1099
1105#define ANY_OP_EXACT_OVERLOAD(ret, op, params, const_) \
1106 ANY_OP_EXACT_OVERLOAD_MAP_NAMED( \
1107 ret, op, _detail_CONCAT(__op__, __COUNTER__), params, const_)
1108
1113#define ANY_OP_EXACT_OVERLOAD_DEF(access, ret, op, name, params, const_, ...) \
1114 ANY_FN_(access, ANY_OVERLOAD(operator op), ret, name, operator op, true, \
1115 const_, (__VA_ARGS__), _detail_EXPAND params)
1116
1122#define ANY_FN_STATIC_PURE(template_params, return_type, name, params, ...) \
1123 ANY_FN_(template_params, return_type, name, \
1124 (_detail_ANYXX_TRAIT_ERROR_MESSAGE(name, return_type)), \
1125 _detail_EXPAND params)
1126
1132#define ANY_FN_STATIC_DEF(template_params, return_type, name, params, ...) \
1133 ANY_FN_(template_params, return_type, name, (__VA_ARGS__), \
1134 _detail_EXPAND params)
1135
1146#define ANY_TYPE(...) (__VA_ARGS__)
1147
1149
1154
1155#define __ANY_MODEL_MAP(trait_, t) \
1156 template <> \
1157 struct trait_##_model_map<_detail_ANYXX_TEMPLATE_ARGS(t)> \
1158 : trait_##_default_model_map<_detail_ANYXX_TEMPLATE_ARGS(t)>
1159
1169#define ANY_TEMPLATE_MODEL_MAP(model_, trait_, trait_types) \
1170 __ANY_MODEL_MAP(trait_, __detail_ANYXX_ADD_HEAD( \
1171 model_, _detail_REMOVE_PARENS(trait_types)))
1172
1182#define TRAIT_TYPE(Name, T, Trait, ...) \
1183 typename Trait::template Name<T, __VA_ARGS__>
1184
1192#define ANY_MODEL_MAP(model_, trait_) __ANY_MODEL_MAP(trait_, model_)
1194
1195#define _detail_ANYXX_TRAIT_ERROR_MESSAGE(name, ret) \
1196 []<typename... Args>([[maybe_unused]] Args...) -> ret { \
1197 static_assert(anyxx::missing_trait_error<T>::not_specialized, \
1198 "'" #name \
1199 "' is missing in the specialization of this proxy_trait!"); \
1200 return {}; \
1201 }
1202
1203namespace anyxx {
1204
1205template <typename, typename = void>
1206struct is_type_complete_impl : std::false_type {};
1207template <typename T>
1208struct is_type_complete_impl<
1209 T, std::enable_if_t<std::is_object<T>::value &&
1210 !std::is_pointer<T>::value && (sizeof(T) > 0)>>
1211 : std::true_type {};
1212template <typename T>
1213constexpr static inline bool is_type_complete = is_type_complete_impl<T>::value;
1214
1215template <class... Ts>
1216struct overloads : Ts... {
1217 using Ts::operator()...;
1218};
1219
1220template <typename T>
1221struct is_variant_impl : std::false_type {};
1222template <typename... Args>
1223struct is_variant_impl<std::variant<Args...>> : std::true_type {};
1224template <typename T>
1225inline constexpr bool is_variant = is_variant_impl<T>::value;
1226
1227#ifdef ANY_DLL_MODE
1228constexpr bool is_in_dll_mode = true;
1229#else
1230constexpr bool is_in_dll_mode = false;
1231#endif
1232
1233class error : public std::runtime_error {
1234 using std::runtime_error::runtime_error;
1235};
1236class type_mismatch_error : public error {
1237 using error::error;
1238};
1239
1240struct member_dispatch {};
1241struct dyn : member_dispatch {};
1242struct static_ : member_dispatch {};
1243
1244template <typename Dispatch>
1245concept is_member_dispatch = std::derived_from<Dispatch, member_dispatch>;
1246static_assert(is_member_dispatch<dyn>);
1247static_assert(is_member_dispatch<static_>);
1248
1249template <typename T>
1250struct missing_trait_error {
1251 static constexpr bool not_specialized = false;
1252};
1253template <typename Value>
1254struct using_;
1255template <typename Type>
1256struct trait_class;
1257
1258using const_void = void const*;
1259using mutable_void = void*;
1260template <typename V>
1261concept voidness =
1262 (std::same_as<V, const_void> || std::same_as<V, mutable_void>);
1263template <voidness Voidness>
1264struct is_const_void_;
1265template <>
1266struct is_const_void_<void*> : std::false_type {};
1267template <>
1268struct is_const_void_<void const*> : std::true_type {};
1269template <typename Voidness>
1270concept is_const_void = is_const_void_<Voidness>::value;
1271
1272class meta_data;
1273
1274template <typename Model>
1275constexpr inline std::size_t compute_model_size() {
1276 if constexpr (std::is_trivially_copyable_v<Model> &&
1277 sizeof(Model) <= sizeof(mutable_void)) {
1278 return 0;
1279 } else {
1280 return sizeof(Model);
1281 }
1282}
1283
1284struct any_v_table;
1285
1286template <bool HasDispatch, typename Trait>
1287struct dispatch_holder;
1288using dispatch_table_function_t = void (*)();
1289using dispatch_table_dispatch_index_t = std::size_t;
1290using dispatch_table_entry_t = unsigned long long;
1291using dispatch_table_t = std::vector<dispatch_table_entry_t>;
1292template <typename AnyVTable, typename Class>
1293dispatch_table_t* dispatch_table_instance_implementation() {
1294 static dispatch_table_t dispatch_table;
1295 return &dispatch_table;
1296}
1297#ifdef ANY_DLL_MODE
1298template <typename AnyVTable, typename Class>
1299dispatch_table_t* dispatch_table_instance();
1300#else
1301template <typename AnyVTable, typename Class>
1302dispatch_table_t* dispatch_table_instance() {
1303 return dispatch_table_instance_implementation<AnyVTable, Class>();
1304}
1305#endif
1306
1309struct undefined {};
1310
1311template <typename VTable, typename Concrete>
1312VTable* v_table_instance();
1313
1317 using v_table_t = observeable_v_table;
1318
1320 template <typename Concrete>
1322 [[maybe_unused]] std::in_place_type_t<Concrete> concrete) {}
1323
1324 static bool static_is_derived_from(const std::type_info& from) {
1325 return typeid(observeable_v_table) == from;
1326 }
1327};
1328
1331 using v_table_t = observeable_rtti_v_table;
1332
1334 template <typename Concrete>
1336 [[maybe_unused]] std::in_place_type_t<Concrete> concrete)
1337 : observeable_v_table(concrete),
1338 get_type_info(+[]() noexcept -> std::type_info const& {
1339 return typeid(Concrete);
1340 }),
1341 is_derived_from_(+[](const std::type_info& from) {
1342 return static_is_derived_from(from);
1343 }) {}
1344
1345 std::type_info const& (*get_type_info)() noexcept;
1346 bool (*is_derived_from_)(const std::type_info&);
1347
1348 static bool static_is_derived_from(const std::type_info& from) {
1349 return typeid(observeable_v_table) == from;
1350 }
1351
1352 meta_data* meta_data_ = nullptr;
1353};
1354
1355template <typename VTable>
1356void set_is_derived_from(auto v_table) {
1357 if constexpr (std::is_base_of_v<observeable_rtti_v_table, VTable>) {
1358 v_table->is_derived_from_ = +[](const std::type_info& from) {
1359 return VTable::static_is_derived_from(from);
1360 };
1361 }
1362}
1363
1366
1369 using v_table_t = any_v_table;
1370 using v_table_base_t = observeable_rtti_v_table;
1371
1373 template <typename Concrete>
1374 explicit any_v_table([[maybe_unused]] std::in_place_type_t<Concrete> concrete)
1375 : observeable_rtti_v_table(concrete),
1376 model_size(compute_model_size<Concrete>()),
1377 allocate(+[] -> mutable_void {
1378 return std::allocator<Concrete>{}.allocate(1);
1379 }),
1380 copy_constructor(+[]([[maybe_unused]] mutable_void placement,
1381 [[maybe_unused]] const_void from) -> mutable_void {
1382 if constexpr (std::is_copy_constructible_v<Concrete>) {
1383 return std::construct_at<Concrete>(
1384 static_cast<Concrete*>(placement),
1385 *static_cast<Concrete const*>(from));
1386 } else {
1387 return nullptr;
1388 };
1389 }),
1390 move_constructor(
1391 +[]([[maybe_unused]] mutable_void placement,
1392 [[maybe_unused]] mutable_void from) -> mutable_void {
1393 if constexpr (std::is_move_constructible_v<Concrete>) {
1394 return std::construct_at<Concrete>(
1395 static_cast<Concrete*>(placement),
1396 std::move(*static_cast<Concrete*>(from)));
1397 } else {
1398 return nullptr;
1399 };
1400 }),
1401 destructor(+[](mutable_void data) noexcept -> void {
1402 std::destroy_at(static_cast<Concrete*>(data));
1403 }),
1404 delete_(+[](mutable_void data) noexcept -> void {
1405 if (!data) return;
1406 auto p = static_cast<Concrete*>(data);
1407 std::destroy_at(p);
1408 std::allocator<Concrete>{}.deallocate(p, 1);
1409 }) {
1410 set_is_derived_from<v_table_t>(this);
1411 }
1412
1413 std::size_t model_size = 0u;
1414 mutable_void (*allocate)();
1415 mutable_void (*copy_constructor)(mutable_void placement, const_void from);
1416 mutable_void (*move_constructor)(mutable_void placement, mutable_void from);
1417 void (*destructor)(mutable_void data) noexcept;
1418 void (*delete_)(mutable_void) noexcept;
1419 static bool static_is_derived_from(const std::type_info& from) {
1420 return typeid(v_table_t) == from
1421 ? true
1422 : v_table_base_t::static_is_derived_from(from);
1423 }
1424};
1425
1426inline bool is_derived_from(const std::type_info& from,
1427 any_v_table const* v_table) {
1428 return v_table->is_derived_from_(from);
1429}
1430
1431inline std::size_t model_size(any_v_table* v_table) {
1432 return v_table ? v_table->model_size : 0u;
1433}
1434inline mutable_void copy_construct_at(any_v_table* v_table,
1435 mutable_void placement, const_void from) {
1436 return v_table->copy_constructor(placement, from);
1437}
1438inline mutable_void copy_construct(any_v_table* v_table, const_void from) {
1439 return copy_construct_at(v_table, v_table->allocate(), from);
1440}
1441inline mutable_void move_construct_at(any_v_table* v_table,
1442 mutable_void placement,
1443 mutable_void from) {
1444 return v_table->move_constructor(placement, from);
1445}
1446inline mutable_void move_construct(any_v_table* v_table, mutable_void from) {
1447 return move_construct_at(v_table, v_table->allocate(), from);
1448}
1449inline void delete_(any_v_table* v_table, mutable_void& data) noexcept {
1450 if (!data) return;
1451 assert(v_table);
1452 v_table->delete_(data);
1453 data = nullptr;
1454} // NOLINT
1455
1456template <typename U>
1457bool type_match(any_v_table* v_table);
1458
1459template <typename U>
1460void check_type_match(any_v_table* v_table) {
1461 if (!type_match<U>(v_table)) throw type_mismatch_error("type mismatch");
1462}
1463
1464template <typename Data>
1465struct proxy_trait;
1466
1467template <typename Proxy>
1468struct basic_proxy_trait {
1469 inline static constexpr bool is_weak = false;
1470 inline static constexpr bool is_lifetime_bound = false;
1471 inline static constexpr bool is_object = true;
1472
1473 static void move_to(auto& to, [[maybe_unused]] auto, auto&& from,
1474 [[maybe_unused]] auto) {
1475 to = std::move(from);
1476 }
1477
1478 static void copy_construct_from(Proxy& to, [[maybe_unused]] void*,
1479 auto const& from, [[maybe_unused]] auto) {
1480 to = from;
1481 }
1482
1483 static void destroy([[maybe_unused]] Proxy const& data,
1484 [[maybe_unused]] void* v_table) {}
1485};
1486
1488
1490template <typename E>
1491concept is_proxy = requires(E e, mutable_void void_data, any_v_table* v_table) {
1492 typename proxy_trait<E>::void_t;
1493 typename proxy_trait<E>::static_dispatch_t;
1494 typename proxy_trait<E>::required_v_table_t;
1495 { proxy_trait<E>::is_constructibile_from_const } -> std::convertible_to<bool>;
1496 { proxy_trait<E>::is_owner } -> std::convertible_to<bool>;
1497 requires requires(proxy_trait<E>::required_v_table_t* required_v_table) {
1498 {
1499 proxy_trait<E>::get_proxy_ptr_in(e, required_v_table)
1500 } -> std::convertible_to<typename proxy_trait<E>::void_t>;
1501 };
1502 { proxy_trait<E>::is_weak } -> std::convertible_to<bool>;
1503 { proxy_trait<E>::clone_from(void_data, v_table) };
1504 { proxy_trait<E>::is_lifetime_bound } -> std::convertible_to<bool>;
1505 { proxy_trait<E>::is_object } -> std::convertible_to<bool>;
1506};
1507
1508template <typename T>
1509struct is_type_class_impl : std::false_type {};
1510template <typename T>
1511struct is_type_class_impl<trait_class<T>> : std::true_type {};
1512template <typename T>
1513inline constexpr bool is_type_class =
1514 is_proxy<T> && is_type_class_impl<T>::value;
1515
1516struct observeable_trait {
1517 template <typename>
1518 static constexpr bool modeled_by() {
1519 return true;
1520 }
1521 using v_table_t = observeable_v_table;
1522};
1523struct observeable_rtti_trait : observeable_trait {
1524 using v_table_t = observeable_rtti_v_table;
1525};
1526struct base_trait : observeable_rtti_trait {
1527 using v_table_t = any_v_table;
1528};
1529
1530template <typename Model>
1531concept is_base_trait_model = true;
1532
1534template <typename T>
1536 std::derived_from<typename T::v_table_t, observeable_v_table>;
1537
1538template <is_proxy Proxy, typename Trait = base_trait>
1539class any;
1540
1542template <typename Proxy>
1543concept is_dyn =
1544 is_proxy<Proxy> && voidness<typename proxy_trait<Proxy>::static_dispatch_t>;
1545
1546template <typename I>
1547concept is_proxy_holder_impl = requires(I i) {
1548 typename I::proxy_t;
1549 typename I::proxy_trait_t;
1550};
1551template <typename I>
1552concept is_proxy_holder = is_proxy_holder_impl<std::decay_t<I>>;
1553
1554template <typename I>
1555concept is_any_impl = is_proxy_holder_impl<I> &&
1556 requires(I::proxy_t ed) { typename I::v_table_t; };
1557template <typename I>
1558concept is_any = is_any_impl<std::decay_t<I>>;
1559
1560template <class E>
1561concept is_typed_any = is_any<E> && requires(E e) {
1562 typename E::proxy_trait_t;
1563 typename E::value_t;
1564 { E::is_const } -> std::convertible_to<bool>;
1565};
1566
1567template <typename ConstructedWith, typename Proxy, typename BASE>
1568concept erased_constructibile_for =
1569 (!std::derived_from<std::remove_cvref_t<ConstructedWith>, BASE> &&
1570 !is_proxy<std::remove_cvref_t<ConstructedWith>> &&
1571 (!std::is_const_v<std::remove_reference_t<ConstructedWith>> ||
1572 proxy_trait<Proxy>::is_constructibile_from_const));
1573
1574template <typename ConstructedWith, typename Proxy>
1575concept constructibile_for =
1576 (proxy_trait<Proxy>::template is_constructibile_from<
1577 ConstructedWith>::value) ||
1578 (erased_constructibile_for<ConstructedWith, Proxy, any<Proxy>> &&
1579 !is_proxy_holder<ConstructedWith> &&
1580 !is_typed_any<std::remove_cvref_t<ConstructedWith>>);
1581
1582template <is_proxy Data>
1583using data_void = proxy_trait<Data>::void_t;
1584
1585template <typename Proxy>
1586concept is_const_data = is_proxy<Proxy> && is_const_void<data_void<Proxy>>;
1587
1588template <typename Proxy>
1589concept is_object_proxy = is_proxy<Proxy> && proxy_trait<Proxy>::is_object;
1590
1591template <typename Proxy>
1592concept is_weak_data = is_proxy<Proxy> && proxy_trait<Proxy>::is_weak;
1593
1594template <typename Proxy>
1595concept is_lifetime_bound =
1596 is_proxy<Proxy> && proxy_trait<Proxy>::is_lifetime_bound;
1597
1598template <bool ToIsConst, bool FromIsConst, bool FromIsWeak>
1599concept const_correct_move_to_from =
1600 !FromIsWeak && ((ToIsConst == FromIsConst) || !FromIsConst);
1601
1602constexpr inline bool is_const_correct_call_for_proxy_and_self(
1603 bool call_is_const, bool proxy_is_const, bool self_is_const, bool exact) {
1604 if (call_is_const) {
1605 if (exact) {
1606 return (call_is_const == proxy_is_const);
1607 } else {
1608 return true;
1609 }
1610 }
1611
1612 if (proxy_is_const || self_is_const) return false;
1613
1614 if (exact)
1615 return (call_is_const == proxy_is_const);
1616 else
1617 return true;
1618}
1619
1620template <typename CALL, typename Proxy, bool SelfIsConst, bool Exact>
1621concept const_correct_call_for_proxy_and_self =
1622 is_object_proxy<Proxy> && !is_weak_data<Proxy> && voidness<CALL> &&
1623 is_proxy<Proxy> &&
1624 is_const_correct_call_for_proxy_and_self(
1625 is_const_void<CALL>, is_const_data<Proxy>, SelfIsConst, Exact);
1626
1627template <is_proxy Proxy, typename From>
1628Proxy erased(From&& from) {
1629 return proxy_trait<Proxy>::erase(std::forward<From>(from));
1630}
1631
1632template <is_proxy Proxy, typename ConstructedWith>
1633using unerased =
1634 proxy_trait<Proxy>::template unerased<std::decay_t<ConstructedWith>>;
1635
1636template <is_proxy Proxy>
1637void const* get_proxy_ptr(
1638 Proxy const& vv, typename proxy_trait<Proxy>::required_v_table_t* v_table)
1639 requires std::same_as<void const*, typename proxy_trait<Proxy>::void_t>
1640{
1641 return proxy_trait<Proxy>::get_proxy_ptr_in(vv, v_table);
1642}
1643template <is_proxy Proxy>
1644void* get_proxy_ptr(Proxy const& vv,
1645 typename proxy_trait<Proxy>::required_v_table_t* v_table)
1646 requires std::same_as<void*, typename proxy_trait<Proxy>::void_t>
1647{
1648 return proxy_trait<Proxy>::get_proxy_ptr_in(vv, v_table);
1649}
1650
1651template <typename U>
1652auto unchecked_unerase_cast(void const* p) {
1653 return static_cast<U const*>(p);
1654}
1655template <typename U>
1656auto unchecked_unerase_cast(void* p) {
1657 return static_cast<U*>(p);
1658}
1659
1660template <typename U, is_proxy Proxy>
1661auto unchecked_unerase_cast(
1662 Proxy const& o, typename proxy_trait<Proxy>::required_v_table_t* v_table) {
1663 return unchecked_unerase_cast<U>(get_proxy_ptr(o, v_table));
1664}
1665template <typename U, is_proxy Proxy>
1666auto unchecked_unerase_cast(
1667 Proxy const& o, typename proxy_trait<Proxy>::required_v_table_t* v_table)
1668 requires(!is_const_data<Proxy>)
1669{
1670 return unchecked_unerase_cast<U>(get_proxy_ptr(o, v_table));
1671}
1672
1673template <typename U, is_proxy Proxy>
1674auto unerase_cast(Proxy const& o, any_v_table* v_table) {
1675 check_type_match<U>(v_table);
1676 return unchecked_unerase_cast<U>(o, v_table);
1677}
1678template <typename U, is_proxy Proxy>
1679U const* unerase_cast_if(Proxy const& o, any_v_table* v_table) {
1680 if (type_match<U>(v_table)) return unchecked_unerase_cast<U>(o, v_table);
1681 return nullptr;
1682}
1683template <typename U, is_proxy Proxy>
1684U* unerase_cast_if(Proxy const& o, any_v_table* v_table)
1685 requires(!is_const_data<Proxy>)
1686{
1687 if (type_match<U>(v_table)) return unchecked_unerase_cast<U>(o, v_table);
1688 return nullptr;
1689}
1690
1691// --------------------------------------------------------------------------------
1692// (un)erased data using_
1693
1694static_assert(std::is_const_v<std::remove_reference_t<int const&>>);
1695static_assert(!std::is_const_v<std::remove_reference_t<int&>>);
1696static_assert(!std::is_const_v<std::remove_reference_t<int>>);
1697
1700
1701template <typename V>
1702struct proxy_trait<using_<V>> : basic_proxy_trait<using_<V>> {
1703 using void_t = std::conditional_t<std::is_const_v<std::remove_reference_t<V>>,
1704 const_void, mutable_void>;
1705 using static_dispatch_t = V;
1706 using required_v_table_t = observeable_v_table;
1707 static constexpr bool is_constructibile_from_const = true;
1708 template <typename ConstructedWith>
1709 struct is_constructibile_from {
1710 static constexpr bool value = std::is_constructible_v<
1711 V, ConstructedWith>; // && !is_any<ConstructedWith>;
1712 };
1713 static constexpr bool is_owner = true;
1714 static auto clone_from([[maybe_unused]] const_void data_ptr,
1715 [[maybe_unused]] any_v_table* v_table) {
1716 return void_t{};
1717 }
1718
1719 static auto get_proxy_ptr_in(auto& val,
1720 [[maybe_unused]] observeable_v_table* v_table) {
1721 return &val;
1722 }
1723
1724 template <typename ConstructedWith>
1725 using unerased = ConstructedWith;
1726
1727 static auto construct_in_place(V&& v) { return std::move(v); }
1728 template <typename... Args>
1729 static auto construct_type_in_place([[maybe_unused]] Args&&... args) {
1730 return V{std::forward<Args>(args)...};
1731 }
1732 template <typename Vx>
1733 static auto erase(Vx&& v) {
1734 return using_<V>{std::forward<Vx>(v)};
1735 }
1736};
1737
1738template <typename Type>
1739struct proxy_trait<trait_class<Type>> : basic_proxy_trait<trait_class<Type>> {
1740 using void_t = const_void;
1741 using static_dispatch_t = Type;
1742 static constexpr bool is_constructibile_from_const = true;
1743 static constexpr bool is_object = false;
1744 using required_v_table_t = observeable_v_table;
1745 template <typename ConstructedWith>
1746 struct is_constructibile_from {
1747 static constexpr bool value = true;
1748 };
1749 static constexpr bool is_owner = false;
1750 static auto clone_from([[maybe_unused]] const_void data_ptr,
1751 [[maybe_unused]] any_v_table* v_table) {}
1752
1753 static auto get_proxy_ptr_in([[maybe_unused]] auto& val,
1754 [[maybe_unused]] void* v_table) {
1755 return nullptr;
1756 }
1757
1758 template <typename ConstructedWith>
1759 using unerased = ConstructedWith;
1760
1761 static auto construct_in_place(auto) {}
1762 template <typename... Args>
1763 static auto construct_type_in_place([[maybe_unused]] Args&&... args) {}
1764 template <typename Vx>
1765 static auto erase([[maybe_unused]] Vx&& v) {
1766 return trait_class<Vx>{};
1767 }
1768};
1769
1779template <template <typename> typename Any, is_proxy Proxy, typename... Types>
1780using vany_variant = std::variant<Any<Proxy>, Types...>;
1781
1783template <template <typename> typename Any, is_proxy Proxy, typename... Types>
1784using make_vany = Any<using_<vany_variant<Any, Proxy, Types...>>>;
1785
1786template <typename VanyVariant>
1787struct vany_variant_trait {
1788 using vany_variant_val = VanyVariant;
1789 using vany_variant = typename VanyVariant::value_t;
1790 template <typename... Types>
1791 struct concrete_variant_impl;
1792 template <typename First, typename... Types>
1793 struct concrete_variant_impl<std::variant<First, Types...>> {
1794 using type = std::variant<Types...>;
1795 };
1796 using concrete_variant = typename concrete_variant_impl<vany_variant>::type;
1797 using any_in_variant = typename std::variant_alternative_t<0, vany_variant>;
1798};
1799
1800template <typename Vany>
1801struct vany_type_trait {
1802 using vany = Vany;
1803 using vany_variant = typename Vany::proxy_t;
1804 using concrete_variant =
1805 typename vany_variant_trait<vany_variant>::concrete_variant;
1806 using any_in_variant =
1807 typename vany_variant_trait<vany_variant>::any_in_variant;
1808};
1809
1810template <template <typename> typename Any, is_proxy Proxy, typename... Types>
1811struct proxy_trait<using_<vany_variant<Any, Proxy, Types...>>>
1812 : basic_proxy_trait<using_<vany_variant<Any, Proxy, Types...>>> {
1813 using vany_variant_t = vany_variant<Any, Proxy, Types...>;
1814 using void_t = typename proxy_trait<Proxy>::void_t;
1815 using required_v_table_t = observeable_v_table;
1816 using static_dispatch_t = vany_variant_t;
1817 static constexpr bool is_constructibile_from_const =
1818 proxy_trait<Proxy>::is_constructibile_from_const;
1819 template <typename ConstructedWith>
1820 struct is_constructibile_from {
1821 static constexpr bool value =
1822 std::is_constructible_v<vany_variant_t, ConstructedWith>;
1823 };
1824 static constexpr bool is_owner = proxy_trait<Proxy>::is_owner;
1825 static constexpr bool is_weak =
1826 proxy_trait<Proxy>::is_weak; // cppcheck-suppress
1827 // duplInheritedMember
1828 static auto clone_from([[maybe_unused]] const_void data_ptr,
1829 [[maybe_unused]] any_v_table* v_table) {
1830 return void_t{};
1831 }
1832
1833 static auto get_proxy_ptr_in(auto& val,
1834 [[maybe_unused]] observeable_v_table* v_table) {
1835 return &val;
1836 }
1837
1838 template <typename ConstructedWith>
1839 using unerased = ConstructedWith;
1840
1841 template <typename V>
1842 static vany_variant_t construct_in_place(V&& v) {
1843 return using_<vany_variant_t>{std::forward<V>(v)};
1844 }
1845 template <typename T, typename... Args>
1846 static auto construct_type_in_place([[maybe_unused]] Args&&... args) {
1847 return using_<vany_variant_t>{T{std::forward<Args>(args)...}};
1848 }
1849 template <typename Vx>
1850 static auto erase(Vx&& v) {
1851 return using_<vany_variant_t>{std::forward<Vx>(v)};
1852 }
1853};
1854
1855// --------------------------------------------------------------------------------
1856// erased data observer
1857
1858template <voidness Voidness>
1859using observer = Voidness;
1863using cref = observer<const_void>;
1867using mutref = observer<mutable_void>;
1868
1869template <voidness Voidness>
1870struct observer_trait : basic_proxy_trait<Voidness> {
1871 using void_t = Voidness;
1872 using static_dispatch_t = void_t;
1873 using required_v_table_t = observeable_v_table;
1874 static constexpr bool is_const = is_const_void<void_t>;
1875 static constexpr bool is_constructibile_from_const = is_const;
1876 static constexpr bool is_lifetime_bound = true;
1877 template <typename ConstructedWith>
1878 struct is_constructibile_from {
1879 static constexpr bool value = false;
1880 };
1881 static constexpr bool is_owner = false;
1882 static auto clone_from([[maybe_unused]] const_void data_ptr,
1883 [[maybe_unused]] any_v_table* v_table) {
1884 return void_t{};
1885 }
1886 static void move_to(Voidness& to, [[maybe_unused]] auto, Voidness from,
1887 [[maybe_unused]] auto) {
1888 to = from;
1889 }
1890
1891 static Voidness get_proxy_ptr_in(
1892 const auto& ptr, [[maybe_unused]] observeable_v_table* v_table) {
1893 return ptr;
1894 }
1895
1896 template <typename ConstructedWith>
1897 using unerased = ConstructedWith;
1898
1899 template <typename V>
1900 static auto construct_in_place(V&&) {
1901 static_assert(false);
1902 return nullptr;
1903 }
1904 template <typename T, typename... Args>
1905 static auto construct_type_in_place([[maybe_unused]] Args&&... args) {
1906 static_assert(false);
1907 return nullptr;
1908 }
1909 template <typename V>
1910 static auto erase(V& v) {
1911 static_assert(!std::is_const_v<std::remove_reference_t<V>>);
1912 return static_cast<Voidness>(&v);
1913 }
1914 template <typename V>
1915 static auto erase(const V& v)
1916 requires(is_const)
1917 {
1918 return static_cast<Voidness>(&v);
1919 }
1920};
1921
1922template <>
1923struct proxy_trait<cref> : observer_trait<cref> {};
1924template <>
1925struct proxy_trait<mutref> : observer_trait<mutref> {};
1926
1927static_assert(proxy_trait<cref>::is_const);
1928static_assert(!proxy_trait<mutref>::is_const);
1929static_assert(is_proxy<cref>);
1930static_assert(is_proxy<mutref>);
1931static_assert(is_proxy<mutref>);
1932static_assert(is_proxy<cref>);
1933
1934// --------------------------------------------------------------------------------
1935// erased data unique
1936
1947struct unique {
1948 mutable_void ptr = nullptr;
1949 explicit unique(mutable_void p = nullptr) : ptr(p) {}
1950 unique(unique const&) = delete;
1951 unique& operator=(unique const&) = delete;
1952 unique(unique&& other) noexcept { std::swap(ptr, other.ptr); }
1953 unique& operator=(unique&& other) noexcept {
1954 assert(!ptr);
1955 std::swap(ptr, other.ptr);
1956 return *this;
1957 };
1958 ~unique() = default;
1959 explicit operator bool() const { return static_cast<bool>(ptr); }
1960};
1961
1962template <>
1963struct proxy_trait<unique> : basic_proxy_trait<unique> {
1964 using void_t = void*;
1965 using static_dispatch_t = void_t;
1966 using required_v_table_t = observeable_v_table;
1967 template <typename V>
1968 using typed_t = std::decay_t<V>;
1969 static constexpr bool is_constructibile_from_const = true;
1970 template <typename ConstructedWith>
1971 struct is_constructibile_from {
1972 static constexpr bool value = false;
1973 };
1974 static constexpr bool is_owner = true;
1975 static auto clone_from([[maybe_unused]] const_void data_ptr,
1976 [[maybe_unused]] any_v_table* v_table) {
1977 return unique{copy_construct(v_table, data_ptr)};
1978 }
1979 static void move_to(unique& to, any_v_table* v_table_to, unique&& from,
1980 [[maybe_unused]] any_v_table* v_table_from) {
1981 mutable_void old = nullptr;
1982 std::swap(to.ptr, old);
1983 std::swap(to.ptr, from.ptr);
1984 delete_(v_table_to, old);
1985 }
1986
1987 static void* get_proxy_ptr_in(const auto& ptr,
1988 [[maybe_unused]] observeable_v_table* v_table) {
1989 return ptr.ptr;
1990 }
1991
1992 static void destroy(unique& u, any_v_table* v_table) {
1993 assert(v_table || !u.ptr);
1994 if (v_table) delete_(v_table, u.ptr);
1995 }
1996
1997 template <typename ConstructedWith>
1998 struct unerased_impl {
1999 using type = std::decay_t<ConstructedWith>;
2000 };
2001 template <typename V>
2002 struct unerased_impl<std::unique_ptr<V>> {
2003 using type = std::decay_t<V>;
2004 };
2005 template <typename ConstructedWith>
2006 using unerased = unerased_impl<ConstructedWith>::type;
2007
2008 template <typename V>
2009 static auto construct_in_place(V&& v) {
2010 return unique{new V{std::forward<V>(v)}};
2011 }
2012 template <typename T, typename... Args>
2013 static auto construct_type_in_place(Args&&... args) {
2014 return unique{new T{std::forward<Args>(args)...}};
2015 }
2016 template <typename V>
2017 static auto erase(std::unique_ptr<V>&& v) {
2018 return unique{v.release()};
2019 }
2020};
2021
2022static_assert(is_proxy<unique>);
2023
2033using shared = std::shared_ptr<void const>;
2037using weak = std::weak_ptr<void const>;
2038
2039template <>
2040struct proxy_trait<shared> : basic_proxy_trait<shared> {
2041 using void_t = void const*;
2042 using static_dispatch_t = void_t;
2043 using required_v_table_t = observeable_v_table;
2044 template <typename V>
2045 using typed_t = const std::decay_t<V>;
2046 static constexpr bool is_constructibile_from_const = true;
2047 template <typename ConstructedWith>
2048 struct is_constructibile_from {
2049 static constexpr bool value = false;
2050 };
2051 static constexpr bool is_owner = true;
2052 static auto clone_from(const_void data_ptr, any_v_table* v_table) {
2053 return shared{copy_construct(v_table, data_ptr), v_table->delete_};
2054 }
2055 static void move_to(shared& to, [[maybe_unused]] any_v_table* v_table_to,
2056 shared&& from, [[maybe_unused]] auto) {
2057 to = std::move(from);
2058 }
2059 static void move_to(shared& to, [[maybe_unused]] any_v_table* v_table_to,
2060 unique from, any_v_table* v_table) {
2061 mutable_void p = nullptr;
2062 std::swap(from.ptr, p);
2063 to = shared{p, v_table->delete_};
2064 }
2065
2066 static void const* get_proxy_ptr_in(
2067 const auto& v, [[maybe_unused]] observeable_v_table* v_table) {
2068 return v.get();
2069 }
2070
2071 template <typename ConstructedWith>
2072 struct unerased_impl {
2073 using type = std::decay_t<ConstructedWith>;
2074 };
2075 template <typename V>
2076 struct unerased_impl<std::shared_ptr<V>> {
2077 using type = std::decay_t<V>;
2078 };
2079 template <typename ConstructedWith>
2080 using unerased = unerased_impl<ConstructedWith>::type;
2081
2082 template <typename V>
2083 static auto construct_in_place(V&& v) {
2084 return std::make_shared<V>(std::forward<V>(v));
2085 }
2086 template <typename T, typename... Args>
2087 static auto construct_type_in_place(Args&&... args) {
2088 return std::make_shared<T>(std::forward<Args>(args)...);
2089 }
2090 template <typename V>
2091 static auto erase(std::shared_ptr<V> const& v) {
2092 return static_pointer_cast<void const>(v);
2093 }
2094};
2095
2096template <>
2097struct proxy_trait<weak> : basic_proxy_trait<weak> {
2098 using void_t = void const*;
2099 using static_dispatch_t = void_t;
2100 using required_v_table_t = observeable_v_table;
2101 template <typename V>
2102 using typed_t = const std::decay_t<V>;
2103 static constexpr bool is_constructibile_from_const = true;
2104 template <typename ConstructedWith>
2105 struct is_constructibile_from {
2106 static constexpr bool value = false;
2107 };
2108 static constexpr bool is_owner = false;
2109 static constexpr bool is_weak = // NOLINT([duplInheritedMember)
2110 true; // cppcheck-suppress duplInheritedMember
2111 static auto clone_from([[maybe_unused]] const_void data_ptr, // NOLINT
2112 [[maybe_unused]] any_v_table* v_table) {
2113 return weak{};
2114 }
2115
2116 static void const* get_proxy_ptr_in(
2117 [[maybe_unused]] const auto& ptr,
2118 [[maybe_unused]] observeable_v_table* v_table) {
2119 return nullptr;
2120 }
2121
2122 template <typename ConstructedWith>
2123 using unerased = std::decay_t<typename ConstructedWith::element_type>;
2124
2125 template <typename V>
2126 static auto construct_in_place(V&&) {
2127 static_assert(false);
2128 return nullptr;
2129 }
2130 template <typename T, typename... Args>
2131 static auto construct_type_in_place([[maybe_unused]] Args&&... args) {
2132 static_assert(false);
2133 return nullptr;
2134 }
2135 template <typename V>
2136 static auto erase(std::shared_ptr<V> const& v) {
2137 return weak{static_pointer_cast<void const>(v)};
2138 }
2139 template <typename V>
2140 static auto erase(std::weak_ptr<V> const& v) {
2141 return erase(v.lock());
2142 }
2143};
2144
2145static_assert(is_proxy<shared>);
2146static_assert(is_proxy<weak>);
2147
2148// --------------------------------------------------------------------------------
2149// erased data val
2150
2151struct heap_data {
2152 mutable_void ptr = nullptr;
2153 heap_data(heap_data const&) {} // NOLINT(missingMemberCopy)
2154 heap_data& operator=(heap_data const&) {
2155 assert(!ptr);
2156 return *this;
2157 }
2158 explicit heap_data(mutable_void p = nullptr) : ptr(p) {}
2159 heap_data(heap_data&& other) noexcept { std::swap(ptr, other.ptr); }
2160 heap_data& operator=(heap_data&& other) noexcept {
2161 assert(!ptr);
2162 std::swap(ptr, other.ptr);
2163 return *this;
2164 };
2165 ~heap_data() = default;
2166 mutable_void release() noexcept {
2167 mutable_void p = ptr;
2168 ptr = nullptr;
2169 return p;
2170 }
2171 friend void swap(heap_data& l, heap_data& r) noexcept { std::swap(l, r); }
2172};
2173
2174template <bool Trivial>
2175struct local_data : std::array<std::byte, sizeof(mutable_void)> {
2176 static constexpr inline bool is_trivial = Trivial;
2177};
2178
2189union val {
2190 val(mutable_void ptr = 0) : heap{ptr} {}
2191 val([[maybe_unused]] val const& other) noexcept { trivial = other.trivial; }
2192 val& operator=([[maybe_unused]] val const& other) noexcept {
2193 trivial = other.trivial;
2194 return *this;
2195 }
2196 ~val() {}
2197 heap_data heap;
2198 local_data<false> local;
2199 local_data<true> trivial;
2200};
2201
2202template <typename V>
2203auto visit_value(auto&& visitor, V&& v, std::size_t size) -> decltype(auto) {
2204 if (size > sizeof(mutable_void)) {
2205 return std::forward<decltype(visitor)>(visitor)(std::forward<V>(v).heap);
2206 } else if (size > 0) {
2207 return std::forward<decltype(visitor)>(visitor)(std::forward<V>(v).local);
2208 }
2209 assert(size == 0);
2210 return std::forward<decltype(visitor)>(visitor)(std::forward<V>(v).trivial);
2211};
2212
2213template <typename V2>
2214auto visit_value(auto&& visitor, val& v1, std::size_t size1, V2&& v2,
2215 std::size_t size2) -> decltype(auto) {
2216 if (size1 > sizeof(mutable_void)) {
2217 if (size2 > sizeof(mutable_void)) {
2218 return std::forward<decltype(visitor)>(visitor)(
2219 v1.heap, std::forward<V2>(v2).heap);
2220 } else if (size2 > 0) {
2221 return std::forward<decltype(visitor)>(visitor)(
2222 v1.heap, std::forward<V2>(v2).local);
2223 }
2224 assert(size2 == 0);
2225 return std::forward<decltype(visitor)>(visitor)(
2226 v1.heap, std::forward<V2>(v2).trivial);
2227 } else if (size1 > 0) {
2228 if (size2 > sizeof(mutable_void)) {
2229 return std::forward<decltype(visitor)>(visitor)(
2230 v1.local, std::forward<V2>(v2).heap);
2231 } else if (size2 > 0) {
2232 return std::forward<decltype(visitor)>(visitor)(
2233 v1.local, std::forward<V2>(v2).local);
2234 }
2235 assert(size2 == 0);
2236 return std::forward<decltype(visitor)>(visitor)(
2237 v1.local, std::forward<V2>(v2).trivial);
2238 }
2239 assert(size1 == 0);
2240 if (size2 > sizeof(mutable_void)) {
2241 return std::forward<decltype(visitor)>(visitor)(v1.trivial,
2242 std::forward<V2>(v2).heap);
2243 } else if (size2 > 0) {
2244 return std::forward<decltype(visitor)>(visitor)(v1.trivial,
2245 std::forward<V2>(v2).local);
2246 }
2247 assert(size2 == 0);
2248 return std::forward<decltype(visitor)>(visitor)(v1.trivial,
2249 std::forward<V2>(v2).trivial);
2250};
2251
2252template <typename T, typename... Args>
2253auto make_local_value(Args&&... args) {
2254 static_assert(alignof(T) <= alignof(mutable_void));
2255 static_assert(sizeof(T) <= sizeof(mutable_void));
2256 constexpr bool is_trivial = std::is_trivial_v<T>;
2257 using local_data_type = local_data<is_trivial>;
2258 val v;
2259 auto location = static_cast<T*>(static_cast<mutable_void>(v.local.data()));
2260 std::construct_at<T>(location, std::forward<Args>(args)...);
2261 return v;
2262}
2263
2264template <typename T, typename... Args>
2265auto make_value(Args&&... args) {
2266 static_assert(alignof(T) <= alignof(mutable_void));
2267 if constexpr (sizeof(T) <= sizeof(mutable_void)) {
2268 return make_local_value<T>(std::forward<Args>(args)...);
2269 } else {
2270 return val{new T(std::forward<Args>(args)...)};
2271 }
2272}
2273
2274template <>
2275struct proxy_trait<val> : basic_proxy_trait<val> {
2276 using void_t = void*;
2277 using static_dispatch_t = void_t;
2278 using required_v_table_t = any_v_table;
2279 template <typename V>
2280 using typed_t = std::decay_t<V>;
2281 static constexpr bool is_constructibile_from_const = true;
2282 template <typename ConstructedWith>
2283 struct is_constructibile_from {
2284 static constexpr bool value = false;
2285 };
2286 static constexpr bool is_owner = true;
2287 static auto clone_from([[maybe_unused]] const_void data_ptr,
2288 [[maybe_unused]] any_v_table* v_table) {
2289 assert(v_table);
2290 anyxx::val v;
2291 visit_value(overloads{[&](heap_data& heap) {
2292 heap.ptr = copy_construct(v_table, data_ptr);
2293 },
2294 [&]<bool Trivial>(local_data<Trivial>& local) {
2295 copy_construct_at(
2296 v_table,
2297 static_cast<mutable_void>(local.data()),
2298 data_ptr);
2299 }},
2300 v, v_table->model_size);
2301 return v;
2302 }
2303
2304 static void move_to(val& to, [[maybe_unused]] any_v_table* v_table_to,
2305 val&& from, [[maybe_unused]] any_v_table* v_table_from) {
2306 if (!v_table_from && !v_table_to) return;
2307 visit_value(
2308 overloads{
2309 [&](heap_data& t, heap_data& f) {
2310 heap_data old;
2311 std::swap(t, old);
2312 std::swap(t, f);
2313 delete_(v_table_to, old.ptr);
2314 },
2315 [&](heap_data& t, local_data<false>& f) {
2316 delete_(v_table_to, t.ptr);
2317 v_table_from->move_constructor(to.local.data(), f.data());
2318 },
2319 [&](heap_data& t, local_data<true>& f) {
2320 delete_(v_table_to, t.ptr);
2321 to.trivial = std::move(f);
2322 },
2323 [&](local_data<false>& t, heap_data& f) {
2324 if (v_table_to) v_table_to->destructor(t.data());
2325 to.heap.ptr = f.release();
2326 },
2327 [&](local_data<false>& t, local_data<false>& f) {
2328 if (v_table_to) v_table_to->destructor(t.data());
2329 v_table_from->move_constructor(t.data(), f.data());
2330 },
2331 [&](local_data<false>& t, local_data<true>& f) {
2332 if (v_table_to) v_table_to->destructor(t.data());
2333 to.trivial = std::move(f);
2334 },
2335 [&]([[maybe_unused]] local_data<true>& t, heap_data& f) {
2336 to.heap.ptr = f.release();
2337 },
2338 [&]([[maybe_unused]] local_data<true>& t, local_data<false>& f) {
2339 v_table_from->move_constructor(to.local.data(), f.data());
2340 },
2341 [&](local_data<true>& t, local_data<true>& f) {
2342 t = std::move(f);
2343 }},
2344 to, model_size(v_table_to), from, v_table_from->model_size);
2345 }
2346 // TODO implement move from unique
2347 // static void move_to(unique& to, any_v_table* to_v_table, val&& v,
2348 // any_v_table* v_table) {
2349 // assert(v_table);
2350 // auto data_ptr =
2351 // visit_value(overloads{[&](heap_data& heap) { return heap.release();
2352 // },
2353 // [&]<bool Trivial>(local_data<Trivial>& local)
2354 // {
2355 // return move_construct(v_table,
2356 // local.data());
2357 // }},
2358 // v, v_table->model_size);
2359 // proxy_trait<unique>::move_to(to, to_v_table, unique{data_ptr}, v_table);
2360 //}
2361
2362 static void copy_construct_from(val& to, any_v_table* to_v_table,
2363 val const& from, any_v_table* from_v_table) {
2364 if (!from_v_table) return;
2365 visit_value(
2366 overloads{
2367 [&](heap_data& to_data, heap_data const& from_data) {
2368 delete_(to_v_table, to_data.ptr);
2369 to_data.ptr = nullptr;
2370 if (from_data.ptr)
2371 to_data.ptr = copy_construct(from_v_table, from_data.ptr);
2372 },
2373 [&](heap_data& t, local_data<false> const& f) {
2374 delete_(to_v_table, t.ptr);
2375 from_v_table->copy_constructor(to.local.data(), f.data());
2376 },
2377 [&](heap_data& t, local_data<true> const& f) {
2378 delete_(to_v_table, t.ptr);
2379 to.trivial = f;
2380 },
2381 [&](local_data<false>& t, heap_data const& f) {
2382 if (to_v_table) to_v_table->destructor(t.data());
2383 to.heap.ptr = copy_construct(from_v_table, f.ptr);
2384 },
2385 [&](local_data<false>& t, local_data<false> const& f) {
2386 if (to_v_table) to_v_table->destructor(t.data());
2387 from_v_table->copy_constructor(t.data(), f.data());
2388 },
2389 [&](local_data<false>& t, local_data<true> const& f) {
2390 if (to_v_table) to_v_table->destructor(t.data());
2391 to.trivial = f;
2392 },
2393 [&]([[maybe_unused]] local_data<true>& t, heap_data const& f) {
2394 to.heap.ptr = copy_construct(from_v_table, f.ptr);
2395 },
2396 [&]([[maybe_unused]] local_data<true>& t,
2397 local_data<false> const& f) {
2398 from_v_table->copy_constructor(to.local.data(), f.data());
2399 },
2400 [&](local_data<true>& t, local_data<true> const& f) { t = f; }},
2401 to, model_size(to_v_table), from, from_v_table->model_size);
2402 }
2403
2404 static void destroy(val& v, any_v_table* v_table) {
2405 visit_value(overloads{[&](heap_data& heap) {
2406 assert(v_table || !heap.ptr);
2407 if (v_table) delete_(v_table, heap.ptr);
2408 },
2409 [&](local_data<false>& local) {
2410 if (v_table) v_table->destructor(local.data());
2411 },
2412 [&]([[maybe_unused]] local_data<true>& local) {}},
2413 v, model_size(v_table));
2414 }
2415
2416 template <typename V>
2417 static void* get_proxy_ptr_in(V&& v, [[maybe_unused]] any_v_table* v_table) {
2418 if (!v_table) return nullptr;
2419 auto model_size = v_table->model_size;
2420 return visit_value(
2421 overloads{[&](heap_data const& heap) { return heap.ptr; },
2422 [&]<bool Trivial>(
2423 local_data<Trivial> const& local) -> mutable_void {
2424 return static_cast<mutable_void>(
2425 const_cast<std::byte*>(local.data()));
2426 }},
2427 std::forward<V>(v), model_size);
2428 }
2429
2430 template <typename ConstructedWith>
2431 using unerased = ConstructedWith;
2432
2433 template <typename V>
2434 static auto construct_in_place(V&& v) {
2435 return make_value<V>(std::forward<V>(v));
2436 }
2437 template <typename T, typename... Args>
2438 static auto construct_type_in_place(Args&&... args) {
2439 return make_value<T>(std::forward<Args>(args)...);
2440 }
2441 template <typename ConstructedWith>
2442 static auto erase(ConstructedWith&& v) {
2443 return make_value<std::decay_t<ConstructedWith>>(
2444 std::forward<ConstructedWith>(v));
2445 }
2446};
2447
2448static_assert(is_proxy<val>);
2449static_assert(is_object_proxy<val>);
2450
2451// --------------------------------------------------------------------------------
2452// meta data
2453
2454class meta_data;
2455
2456template <typename TYPE>
2457auto& runtime_implementation();
2458
2459#ifdef ANY_DLL_MODE
2460template <typename T>
2461meta_data& get_meta_data();
2462#else
2463template <typename T>
2464meta_data& get_meta_data() {
2465 return runtime_implementation<std::decay_t<T>>();
2466}
2467#endif
2468
2469template <bool dynamic, typename Trait>
2470struct v_table_holder;
2471template <typename Trait>
2472struct v_table_holder<false, Trait> {
2473 struct v_table_t {};
2474
2475 v_table_holder() = default;
2476 explicit v_table_holder(v_table_t*) {}
2477 static void set_v_table_ptr(auto) {}
2478 static auto get_v_table_ptr() { return nullptr; }
2479 template <typename...>
2480 static void init_v_table() {}
2481 static auto release_v_table() { return nullptr; }
2482};
2483
2484template <typename Trait>
2485struct with_open_dispatch : std::false_type {};
2486
2487template <typename Trait>
2488struct v_table_holder<true, Trait> {
2489 public:
2490 using v_table_t = Trait::v_table_t;
2491
2492 private:
2493 v_table_t* v_table_ = nullptr;
2494
2495 public:
2496 v_table_holder() = default;
2497 explicit v_table_holder(v_table_t* v_table) : v_table_(v_table) {}
2498 void set_v_table_ptr(v_table_t* v_table) { v_table_ = v_table; }
2499 // cppcheck-suppress-begin [functionConst, functionStatic]
2500 auto get_v_table_ptr() const { return v_table_; }
2501 // cppcheck-suppress-end [functionConst, functionStatic]
2502 template <typename Proxy, typename Concrete>
2503 void init_v_table() {
2504 v_table_ = v_table_instance<v_table_t, anyxx::unerased<Proxy, Concrete>>();
2505 }
2506 auto release_v_table() { return std::exchange(v_table_, nullptr); }
2507};
2508
2509void insert_function(dispatch_table_t* table, std::size_t index, auto fp) {
2510 if (table->size() <= index) table->resize(index + 1);
2511 auto& entry = table->at(index);
2512 entry = reinterpret_cast<unsigned long long>(fp);
2513}
2514inline dispatch_table_function_t get_function(dispatch_table_t* table,
2515 std::size_t index) {
2516 if (table->size() <= index) return {};
2517 return reinterpret_cast<dispatch_table_function_t>(table->at(index));
2518}
2519
2520inline dispatch_table_dispatch_index_t get_multi_dispatch_index_at(
2521 dispatch_table_t* table, std::size_t index) {
2522 if (table->size() <= index) return {};
2523 if (auto const entry = table->at(index))
2524 return static_cast<dispatch_table_dispatch_index_t>(entry);
2525 else
2526 return {};
2527}
2528inline void set_multi_dispatch_index_at(
2529 dispatch_table_t* table, std::size_t index_multi_dispatch,
2530 dispatch_table_dispatch_index_t
2531 dispatch_index_of_class_in_dispatch_matrix) {
2532 if (table->size() <= index_multi_dispatch)
2533 table->resize(index_multi_dispatch + 1);
2534 auto& entry = table->at(index_multi_dispatch);
2535 entry = dispatch_index_of_class_in_dispatch_matrix;
2536}
2537
2538struct cast_error {
2539 std::type_info const &to, &from;
2540};
2541
2542class meta_data {
2543 const std::type_info& type_info_;
2544 std::vector<any_v_table*> i_table_;
2545
2546 public:
2547 template <typename CLASS>
2548 explicit constexpr meta_data(std::in_place_type_t<CLASS>)
2549 : type_info_(typeid(CLASS)) {}
2550
2551 constexpr const std::type_info& get_type_info() const { return type_info_; }
2552
2553 auto& get_i_table() { return i_table_; }
2554 auto& get_i_table() const { return i_table_; }
2555
2556 std::expected<any_v_table*, cast_error> get_v_table(
2557 std::type_info const& typeid_) const {
2558 auto const& i_table = get_i_table();
2559 for (auto v_table : i_table)
2560 if (is_derived_from(typeid_, v_table)) return v_table;
2561 return std::unexpected(cast_error{.to = typeid_, .from = get_type_info()});
2562 }
2563 auto register_v_table(any_v_table* v_table) {
2564 v_table->meta_data_ = this;
2565 if (std::ranges::find(get_i_table(), v_table) == get_i_table().end())
2566 i_table_.push_back(v_table);
2567 return v_table;
2568 }
2569};
2570
2571template <typename TYPE>
2572auto& runtime_implementation() {
2573 static meta_data meta_data_{std::in_place_type<TYPE>};
2574 return meta_data_;
2575}
2576
2577template <typename VTable, typename Concrete>
2578auto bind_v_table_to_meta_data() {
2579 auto v_table = v_table_instance<VTable, Concrete>();
2580 get_meta_data<Concrete>().register_v_table(v_table);
2581 return v_table;
2582}
2583
2584template <typename U>
2585bool type_match(any_v_table* v_table) {
2586 return v_table->get_type_info() == typeid(std::decay_t<U>);
2587}
2588
2589// --------------------------------------------------------------------------------
2590// borrow erased data
2591
2592template <is_proxy To, is_proxy From>
2593struct borrow_trait;
2594
2595template <typename To, typename From, typename FromVTable>
2596concept borrowable_from =
2597 is_proxy<From> && is_proxy<To> &&
2598 std::derived_from<FromVTable,
2599 typename proxy_trait<To>::required_v_table_t> &&
2600 requires(From f, FromVTable* v_table) {
2601 { borrow_trait<To, From>{}(f, v_table) } -> std::same_as<To>;
2602 };
2603
2604template <typename To, typename From, typename FromVTable>
2605 requires borrowable_from<To, From, FromVTable>
2606To borrow_as(From const& from, FromVTable* v_table) {
2607 return borrow_trait<To, From>{}(from, v_table);
2608}
2609
2610template <is_proxy From>
2611 requires(!is_const_data<From> && !is_weak_data<From>)
2612struct borrow_trait<mutref, From> {
2613 auto operator()(const auto& from, auto* v_table) const {
2614 return mutref{get_proxy_ptr(from, v_table)};
2615 }
2616};
2617template <is_proxy From>
2618 requires(!is_weak_data<From>)
2619struct borrow_trait<cref, From> {
2620 auto operator()(const auto& from, [[maybe_unused]] auto* v_table) const {
2621 return cref{get_proxy_ptr(from, v_table)};
2622 }
2623};
2624template <>
2625struct borrow_trait<shared, shared> {
2626 auto operator()(const auto& from, [[maybe_unused]] auto* v_table) const {
2627 return from;
2628 }
2629};
2630template <>
2631struct borrow_trait<weak, weak> {
2632 auto operator()(const auto& from, [[maybe_unused]] auto* v_table) const {
2633 return from;
2634 }
2635};
2636template <>
2637struct borrow_trait<weak, shared> {
2638 auto operator()(const auto& from, [[maybe_unused]] auto* v_table) const {
2639 return weak{from};
2640 }
2641};
2642
2643static_assert(!borrowable_from<mutref, cref, observeable_v_table>);
2644static_assert(borrowable_from<mutref, mutref, observeable_v_table>);
2645static_assert(borrowable_from<mutref, unique, observeable_v_table>);
2646static_assert(!borrowable_from<mutref, shared, observeable_v_table>);
2647static_assert(!borrowable_from<mutref, weak, observeable_v_table>);
2648static_assert(borrowable_from<mutref, val, any_v_table>);
2649
2650static_assert(borrowable_from<cref, cref, observeable_v_table>);
2651static_assert(borrowable_from<cref, mutref, observeable_v_table>);
2652static_assert(borrowable_from<cref, unique, observeable_v_table>);
2653static_assert(borrowable_from<cref, shared, observeable_v_table>);
2654static_assert(!borrowable_from<cref, weak, observeable_v_table>);
2655static_assert(borrowable_from<cref, val, any_v_table>);
2656
2657static_assert(!borrowable_from<shared, cref, observeable_v_table>);
2658static_assert(!borrowable_from<shared, mutref, observeable_v_table>);
2659static_assert(!borrowable_from<shared, unique, observeable_v_table>);
2660static_assert(borrowable_from<shared, shared, observeable_v_table>);
2661static_assert(!borrowable_from<shared, weak, observeable_v_table>);
2662static_assert(!borrowable_from<shared, val, any_v_table>);
2663
2664static_assert(!borrowable_from<weak, cref, observeable_v_table>);
2665static_assert(!borrowable_from<weak, mutref, observeable_v_table>);
2666static_assert(!borrowable_from<weak, unique, observeable_v_table>);
2667static_assert(borrowable_from<weak, shared, observeable_v_table>);
2668static_assert(borrowable_from<weak, weak, observeable_v_table>);
2669static_assert(!borrowable_from<weak, val, any_v_table>);
2670
2671static_assert(!borrowable_from<unique, cref, observeable_v_table>);
2672static_assert(!borrowable_from<unique, mutref, observeable_v_table>);
2673static_assert(!borrowable_from<unique, unique, observeable_v_table>);
2674static_assert(!borrowable_from<unique, shared, observeable_v_table>);
2675static_assert(!borrowable_from<unique, weak, observeable_v_table>);
2676static_assert(!borrowable_from<unique, val, any_v_table>);
2677
2678static_assert(!borrowable_from<val, cref, observeable_v_table>);
2679static_assert(!borrowable_from<val, mutref, observeable_v_table>);
2680static_assert(!borrowable_from<val, unique, observeable_v_table>);
2681static_assert(!borrowable_from<val, shared, observeable_v_table>);
2682static_assert(!borrowable_from<val, weak, observeable_v_table>);
2683static_assert(!borrowable_from<val, val, any_v_table>);
2684
2685// --------------------------------------------------------------------------------
2686// clone erased data
2687
2688template <is_proxy To>
2689struct can_copy_to;
2690
2691template <typename To>
2692concept cloneable_to = is_proxy<To> && proxy_trait<To>::is_owner;
2693
2694template <is_proxy To, is_proxy From>
2695 requires cloneable_to<To>
2696To clone_to(From const& from, any_v_table* v_table) {
2697 return proxy_trait<To>::clone_from(get_proxy_ptr(from, v_table), v_table);
2698}
2699
2700static_assert(!cloneable_to<mutref>);
2701static_assert(!cloneable_to<cref>);
2702static_assert(cloneable_to<shared>);
2703static_assert(!cloneable_to<weak>);
2704static_assert(cloneable_to<unique>);
2705static_assert(cloneable_to<val>);
2706
2707// --------------------------------------------------------------------------------
2708// move erased data
2709
2710template <typename To, typename From>
2711inline static bool constexpr can_move_to_from = false;
2712
2713template <typename To, typename From>
2714concept moveable_from =
2715 is_proxy<From> && is_proxy<To> && can_move_to_from<To, From>;
2716
2717template <is_proxy X>
2718inline static bool constexpr can_move_to_from<X, X> = true;
2719
2720template <>
2721inline bool constexpr can_move_to_from<shared, unique> = true;
2722
2723template <>
2724inline bool constexpr can_move_to_from<weak, shared> = true;
2725
2726template <voidness To, voidness From>
2727 requires const_correct_move_to_from<is_const_void<To>, is_const_void<From>,
2728 is_weak_data<From>>
2729inline static bool constexpr can_move_to_from<To, From> = true;
2730
2731template <is_proxy To, is_proxy From>
2732 requires moveable_from<To, std::decay_t<From>>
2733void move_to(To& to, any_v_table* to_v_table, From&& from,
2734 any_v_table* from_v_table) {
2735 return proxy_trait<From>::move_to(to, to_v_table, std::move(from),
2736 from_v_table);
2737}
2738
2739static_assert(!moveable_from<mutref, cref>);
2740static_assert(moveable_from<mutref, mutref>);
2741static_assert(!moveable_from<mutref, unique>);
2742static_assert(!moveable_from<mutref, shared>);
2743static_assert(!moveable_from<mutref, weak>);
2744static_assert(!moveable_from<mutref, val>);
2745
2746static_assert(moveable_from<cref, cref>);
2747static_assert(moveable_from<cref, mutref>);
2748static_assert(!moveable_from<cref, unique>);
2749static_assert(!moveable_from<cref, shared>);
2750static_assert(!moveable_from<cref, weak>);
2751static_assert(!moveable_from<cref, val>);
2752
2753static_assert(!moveable_from<shared, cref>);
2754static_assert(!moveable_from<shared, mutref>);
2755static_assert(moveable_from<shared, unique>);
2756static_assert(moveable_from<shared, shared>);
2757static_assert(!moveable_from<shared, weak>);
2758static_assert(!moveable_from<shared, val>);
2759
2760static_assert(!moveable_from<weak, cref>);
2761static_assert(!moveable_from<weak, mutref>);
2762static_assert(!moveable_from<weak, unique>);
2763static_assert(moveable_from<weak, shared>);
2764static_assert(moveable_from<weak, weak>);
2765static_assert(!moveable_from<weak, val>);
2766
2767static_assert(!moveable_from<unique, cref>);
2768static_assert(!moveable_from<unique, mutref>);
2769static_assert(moveable_from<unique, unique>);
2770static_assert(!moveable_from<unique, shared>);
2771static_assert(!moveable_from<unique, weak>);
2772static_assert(!moveable_from<unique, val>);
2773
2774static_assert(!moveable_from<val, cref>);
2775static_assert(!moveable_from<val, mutref>);
2776static_assert(!moveable_from<val, unique>);
2777static_assert(!moveable_from<val, shared>);
2778static_assert(!moveable_from<val, weak>);
2779static_assert(moveable_from<val, val>);
2780
2805template <is_proxy Proxy, typename Trait>
2806class ANYXX_USE_EBO any : public v_table_holder<is_dyn<Proxy>, Trait>, public Trait {
2807 public:
2808 using proxy_t = Proxy;
2809 using proxy_trait_t = proxy_trait<proxy_t>;
2810 using void_t = typename proxy_trait_t::void_t;
2811 using v_table_holder_t = v_table_holder<is_dyn<Proxy>, Trait>;
2812 using trait_t = Trait;
2813 using v_table_t = typename v_table_holder_t::v_table_t;
2814 using T = proxy_trait_t::static_dispatch_t;
2815 using any_value_t = any<val, Trait>;
2816 static constexpr bool dyn = is_dyn<Proxy>;
2817 static_assert(!dyn || has_v_table<Trait>);
2818
2819 protected:
2820 proxy_t proxy_{};
2821
2822 public:
2823 // cppcheck-suppress-begin noExplicitConstructor
2828 template <typename ConstructedWith>
2829 explicit(false) any(ConstructedWith&& constructed_with) // NOLINT
2830 requires constructibile_for<ConstructedWith, Proxy> &&
2831 (!std::same_as<any, std::decay_t<ConstructedWith>>) &&
2832 (!is_lifetime_bound<Proxy>)
2833 : proxy_(
2834 erased<proxy_t>(std::forward<ConstructedWith>(constructed_with))) {
2835 v_table_holder_t::template init_v_table<Proxy, ConstructedWith>();
2836 }
2837
2840 template <typename ConstructedWith>
2841 explicit(false)
2842 any(ConstructedWith&& constructed_with LIFETIMEBOUND) // NOLINT
2843 requires constructibile_for<ConstructedWith, Proxy> &&
2844 (!std::same_as<any, std::decay_t<ConstructedWith>>) &&
2845 (is_lifetime_bound<Proxy>)
2846 : proxy_(
2847 erased<proxy_t>(std::forward<ConstructedWith>(constructed_with))) {
2848 v_table_holder_t::template init_v_table<Proxy, ConstructedWith>();
2849 }
2850 // cppcheck-suppress-end noExplicitConstructor
2858 template <typename V>
2859 requires(!is_lifetime_bound<Proxy>)
2860 any(std::in_place_t, V&& v)
2861 : proxy_(proxy_trait<Proxy>::construct_in_place(std::forward<V>(v))) {
2862 v_table_holder_t::template init_v_table<Proxy, V>();
2863 }
2864
2870 template <typename T, typename... Args>
2871 requires(!is_lifetime_bound<Proxy>)
2872 any(std::in_place_type_t<T>, Args&&... args)
2873 : proxy_(proxy_trait_t::template construct_type_in_place<T>(
2874 std::forward<Args>(args)...)) {
2875 v_table_holder_t::template init_v_table<Proxy, T>();
2876 }
2877
2878 any() = default;
2879 ~any() {
2880 proxy_trait_t::destroy(proxy_, v_table_holder_t::get_v_table_ptr());
2881 }
2882
2883 any(const any& other)
2884 requires(dyn && std::copyable<proxy_t>)
2885 : v_table_holder_t(other.get_v_table_ptr()) {
2886 proxy_trait_t::copy_construct_from(proxy_, nullptr, other.proxy_,
2887 other.get_v_table_ptr());
2888 }
2889 any(const any& other)
2890 requires(!dyn && std::copyable<proxy_t>)
2891 : v_table_holder_t(other.get_v_table_ptr()), proxy_(other.proxy_) {}
2892 any& operator=(any const& other)
2893 requires std::copyable<proxy_t>
2894 {
2895 if (this == &other) return *this;
2896 auto const v_table_ptr = v_table_holder_t::get_v_table_ptr();
2897 proxy_trait_t::copy_construct_from(proxy_, v_table_ptr, other.proxy_,
2898 other.get_v_table_ptr());
2899 v_table_holder_t::set_v_table_ptr(other.get_v_table_ptr());
2900 return *this;
2901 }
2902
2903 template <is_any Other>
2904 explicit(false) any(const Other& other) // NOLINT(noExplicitConstructor)
2905 requires(borrowable_from<proxy_t, typename Other::proxy_t,
2906 typename Other::v_table_t> &&
2907 (!is_dyn<Proxy> ||
2908 std::derived_from<typename Other::v_table_t, v_table_t>))
2909 : v_table_holder_t(other.get_v_table_ptr()),
2910 proxy_(borrow_as<Proxy>(other.proxy_, other.get_v_table_ptr())) {}
2911 template <is_any Other>
2912 any& operator=(Other const& other)
2913 requires(borrowable_from<proxy_t, typename Other::proxy_t,
2914 typename Other::v_table_t> &&
2915 (!is_dyn<Proxy> ||
2916 std::derived_from<typename Other::v_table_t, v_table_t>))
2917 {
2918 v_table_holder_t::set_v_table_ptr(other.get_v_table_ptr());
2919 proxy_ = borrow_as<Proxy>(other.proxy_, other.get_v_table_ptr());
2920 return *this;
2921 }
2922
2923 template <is_proxy OtherErasedData>
2924 requires(moveable_from<proxy_t, OtherErasedData>)
2925 explicit any(OtherErasedData&& proxy, v_table_t* v_table) noexcept
2926 : v_table_holder_t(v_table) {
2927 proxy_trait_t::move_to(proxy_, nullptr, std::move(proxy), v_table);
2928 }
2929 template <is_proxy OtherErasedData>
2930 requires(moveable_from<proxy_t, OtherErasedData> && !dyn)
2931 explicit any(OtherErasedData&& proxy, v_table_t* v_table) noexcept
2932 : v_table_holder_t(v_table), proxy_(std::move(proxy)) {}
2933 template <is_any Other>
2934 explicit(false) any(Other&& other) noexcept // NOLINT(noExplicitConstructor)
2935 requires(moveable_from<proxy_t, typename Other::proxy_t> &&
2936 (!is_dyn<Proxy> ||
2937 std::derived_from<typename Other::v_table_t, v_table_t>))
2938 : any(std::move(other.proxy_), other.release_v_table()) {}
2939 template <is_any Other>
2940 any& operator=(Other&& other) noexcept
2941 requires(moveable_from<proxy_t, typename Other::proxy_t> &&
2942 (!is_dyn<Proxy> ||
2943 std::derived_from<typename Other::v_table_t, v_table_t>))
2944 {
2945 proxy_trait_t::move_to(proxy_, v_table_holder_t::get_v_table_ptr(),
2946 std::move(other.proxy_), other.get_v_table_ptr());
2947 v_table_holder_t::set_v_table_ptr(other.release_v_table());
2948 return *this;
2949 }
2950 template <typename Box>
2951 using type_for = any<Box, Trait>;
2952
2953 template <is_any Friend>
2954 friend inline auto& get_proxy(Friend const& any);
2955 template <is_any Friend>
2956 friend inline auto& get_proxy(Friend& any);
2957 template <is_any Friend>
2958 friend inline decltype(auto) move_proxy(Friend&& any);
2959 template <is_any Friend>
2960 friend inline auto get_proxy_ptr(Friend const& any);
2961
2962 template <is_proxy Other, typename OtherTrait>
2963 friend class any;
2964
2965 template <typename Friend>
2966 requires is_any<Friend> && Friend::dyn
2967 friend inline auto get_v_table(Friend const& any);
2968
2969 template <is_any To, is_any From>
2970 friend inline To unchecked_downcast_to(From from)
2971 requires(
2972 std::derived_from<typename To::v_table_t, typename From::v_table_t>);
2973
2974 explicit operator bool() const {
2975 if constexpr (!voidness<typename proxy_trait_t::static_dispatch_t>) {
2976 if constexpr (is_type_class<proxy_t>) {
2977 return true;
2978 } else {
2979 return proxy_.value_;
2980 }
2981 } else {
2982 auto p = get_proxy_ptr(*this);
2983 return p != nullptr;
2984 }
2985 }
2986};
2987
2988template <is_any Any>
2989inline auto& get_proxy(Any const& any) {
2990 return any.proxy_;
2991}
2992template <is_any Any>
2993inline auto& get_proxy(Any& any) {
2994 return any.proxy_;
2995}
2996template <typename Any>
2997 requires is_any<std::decay_t<Any>> && (!std::decay_t<Any>::dyn)
2998inline auto& get_proxy_value(Any&& any) {
2999 return get_proxy(std::forward<Any>(any)).value_;
3000}
3001template <typename Any>
3002 requires is_any<std::decay_t<Any>> && (!std::decay_t<Any>::dyn)
3003inline auto const& get_proxy_value(Any const& any) {
3004 return get_proxy(any).value_;
3005}
3006template <is_any Any>
3007inline decltype(auto) move_proxy(Any&& any) {
3008 return std::move(any.proxy_);
3009}
3010template <is_any Any>
3011inline auto get_proxy_ptr(Any const& any) {
3012 return get_proxy_ptr(get_proxy(any), get_v_table(any));
3013}
3014
3015template <is_any Any>
3016inline const auto& get_meta_data(Any const& any) {
3017 return *get_v_table(any)->meta_data_;
3018}
3019
3020template <is_any Any>
3021inline std::type_info const& get_type_info(Any const& any) {
3022 return get_v_table(any)->get_type_info();
3023}
3024
3025template <is_any Any>
3026 requires std::derived_from<typename Any::v_table_t, observeable_rtti_v_table>
3027bool is_derived_from(const std::type_info& from, Any const& any) {
3028 return get_v_table(any)->is_derived_from_(from);
3029}
3030template <is_any From, is_any Any>
3031 requires std::derived_from<typename From::v_table_t,
3032 observeable_rtti_v_table> &&
3033 std::derived_from<typename Any::v_table_t, observeable_rtti_v_table>
3034bool is_derived_from(Any const& any) {
3035 return is_derived_from(typeid(typename From::v_table_t), any);
3036}
3037
3038template <typename To>
3039 requires(!is_any<To> && std::derived_from<To, observeable_v_table>)
3040auto unchecked_v_table_downcast_to(observeable_v_table* v_table) {
3041 return static_cast<To*>(v_table);
3042}
3043template <typename To>
3044 requires is_any<To> &&
3045 std::derived_from<typename To::v_table_t, observeable_v_table>
3046auto unchecked_v_table_downcast_to(observeable_v_table* v_table) {
3047 return unchecked_v_table_downcast_to<typename To::v_table_t>(v_table);
3048}
3049
3050template <typename Any>
3051 requires is_any<Any> && Any::dyn
3052inline auto get_v_table(Any const& any) {
3053 return unchecked_v_table_downcast_to<Any>(any.get_v_table_ptr());
3054}
3055
3056template <is_any To, is_any From>
3057inline To unchecked_downcast_to(From from)
3058 requires(std::derived_from<typename To::v_table_t, typename From::v_table_t>)
3059{
3060 return To{std::move(from.proxy_),
3061 unchecked_v_table_downcast_to<To>(get_v_table(from))};
3062}
3063
3069
3073template <is_any To, is_any From>
3074inline std::optional<To> downcast_to(From from)
3075 requires(std::derived_from<typename To::v_table_t, typename From::v_table_t>)
3076{
3077 if (is_derived_from<To>(from))
3078 return {unchecked_downcast_to<To>(std::move(from))};
3079 return {};
3080}
3081
3082template <typename U, is_any Any>
3083inline auto unchecked_unerase_cast(Any const& o) {
3084 return unchecked_unerase_cast<U>(get_proxy(o), get_v_table(o));
3085}
3089template <typename U, typename Any>
3090 requires is_any<Any> && Any::dyn
3091inline auto unerase_cast(Any const& o) {
3092 return unerase_cast<U>(get_proxy(o), get_v_table(o));
3093}
3094
3097template <typename U, typename Any>
3098 requires is_any<Any> && Any::dyn
3099inline auto unerase_cast_if(Any const& o) {
3100 return unerase_cast_if<U>(get_proxy(o), get_v_table(o));
3101}
3102
3115template <typename Value>
3116struct using_ {
3117 template <typename V>
3118 requires(!std::same_as<std::decay_t<V>, using_>)
3119 using_(V&& v) : value_(std::forward<V>(v)) {}
3120 Value value_;
3121 using value_t = Value;
3122 operator Value() const { return value_; }
3125 template <typename Trait>
3126 using as = any<using_<Value>, Trait>;
3127};
3128
3131template <typename Type, typename Trait>
3132using use_as = any<using_<Type>, Trait>;
3133
3136template <typename Type, template <typename...> typename Trait, typename... Ts>
3137using use_as_ = any<using_<Type>, Trait<Ts...>>;
3138
3142template <typename Trait, typename T>
3143auto trait_as(T&& v) {
3144 return any<anyxx::using_<std::decay_t<T>>, Trait>{std::forward<T>(v)};
3145}
3146
3152template <typename Type>
3154 using value_t = Type;
3155};
3156
3162template <typename Type, typename Trait>
3164
3168template <typename Type, typename Trait>
3169static inline any_trait_class<Type, Trait> trait_class_;
3170
3171template <typename VTable, typename Concrete>
3172VTable* v_table_instance() {
3173 static VTable v_table{std::in_place_type<Concrete>};
3174 return &v_table;
3175}
3176
3177template <typename I>
3178concept has_open_dispatch_enabeled =
3179 is_any<I> && I::v_table_t::open_dispatch_enabeled;
3180
3181template <typename Trait>
3182struct dispatch_holder<false, Trait> {
3183 static void set_dispatch_table([[maybe_unused]] dispatch_table_t* t) {}
3184};
3185template <typename Trait>
3186struct dispatch_holder<true, Trait> {
3187 void set_dispatch_table(dispatch_table_t* t) { dispatch_table = t; }
3188 dispatch_table_t* dispatch_table = nullptr;
3189};
3190
3191template <is_any ToAny>
3192auto query_v_table(any_v_table* from)
3193 -> std::expected<typename ToAny::v_table_t*, anyxx::cast_error> {
3194 using v_table_t = typename ToAny::v_table_t;
3195 if (from->is_derived_from_(typeid(v_table_t)))
3196 return static_cast<v_table_t*>(from);
3197 return from->meta_data_->get_v_table(typeid(v_table_t))
3198 .transform([](auto v_table) { return static_cast<v_table_t*>(v_table); });
3199}
3200
3201template <typename ToAny>
3202auto query_v_table(any_v_table* from) {
3203 return find_v_table<ToAny>(*from->meta_data_);
3204}
3205
3206// --------------------------------------------------------------------------------
3207// any parameter translation
3208
3209struct self {};
3210
3211template <typename Param>
3212struct jacket_return;
3213
3214template <typename Param>
3215 requires(!std::is_reference_v<Param>)
3216struct jacket_return<Param> {
3217 template <typename Sig>
3218 static Param forward(Sig&& sig, auto&&) {
3219 return std::forward<Sig>(sig);
3220 }
3221};
3222template <typename Param>
3223 requires std::is_reference_v<Param>
3224struct jacket_return<Param> {
3225 template <typename Sig>
3226 static decltype(auto) forward(Sig&& sig, auto&&) {
3227 return std::forward<Sig>(sig);
3228 }
3229};
3230static_assert(!is_type_class<val>);
3231template <>
3232struct jacket_return<self> {
3233 template <typename Sig, typename Any>
3234 static decltype(auto) forward(Sig&& sig, Any const&) {
3235 using sig_t = std::decay_t<Sig>;
3236 if constexpr (is_type_class<typename std::decay_t<Any>::proxy_t>) {
3237 using target_t =
3238 any<using_<typename Any::proxy_t::value_t>, typename Any::trait_t>;
3239 if constexpr (is_any<sig_t>) {
3240 return target_t{get_proxy_value(std::forward<Sig>(sig))};
3241 } else {
3242 return target_t{std::forward<Sig>(sig)};
3243 }
3244 } else {
3245 if constexpr (is_any<sig_t> && !Any::dyn) {
3246 return Any{get_proxy_value(sig)};
3247 } else {
3248 return Any{std::forward<Sig>(sig)};
3249 }
3250 }
3251 }
3252};
3253template <>
3254struct jacket_return<self&> {
3255 static auto& forward(auto, auto&& any) {
3256 return any; // "return *this" semantics!
3257 }
3258};
3259
3260TRAIT_EX(translate_sig, , ,
3261 (ANY_TYPE(((AnyValue)), v_table_param, void, (T)),
3262 ANY_TYPE(((AnyValue)), v_table_return, void, (T)),
3263 ANY_TYPE(((Model)), map_return, void, (T)),
3264 ANY_TYPE(((Model)), concept_arg, void, (T))),
3265 ())
3266ANY_MODEL_MAP((self), translate_sig) {
3267 template <typename AnyValue>
3268 using v_table_param = any<cref>;
3269 template <typename AnyValue>
3270 using v_table_return = AnyValue;
3271 template <typename Model>
3272 using map_return = Model;
3273 template <typename Model>
3274 using concept_arg = Model;
3275};
3276ANY_MODEL_MAP((self const&), translate_sig) {
3277 template <typename AnyValue>
3278 using v_table_param = any<cref>;
3279 template <typename AnyValue>
3280 using v_table_return = int; // dummy
3281 template <typename Model>
3282 using map_return = Model const&;
3283 template <typename Model>
3284 using concept_arg = Model const&;
3285};
3286ANY_MODEL_MAP((self&), translate_sig) {
3287 template <typename AnyValue>
3288 using v_table_param = any<mutref>;
3289 template <typename AnyValue>
3290 using v_table_return = int; // dummy
3291 template <typename Model>
3292 using map_return = Model&;
3293 template <typename Model>
3294 using concept_arg = Model&;
3295};
3296template <typename AnyValue, typename Param>
3297using v_table_param = TRAIT_TYPE(v_table_param, Param, translate_sig, AnyValue);
3298template <typename AnyValue, typename Return>
3299using v_table_return = TRAIT_TYPE(v_table_return, Return, translate_sig,
3300 AnyValue);
3301template <typename Model, typename Param>
3302using map_return = TRAIT_TYPE(map_return, Param, translate_sig, Model);
3303template <typename Model, typename Param>
3304using concept_arg = TRAIT_TYPE(concept_arg, Param, translate_sig, Model);
3305
3306//+++ This metafunctions cannot be expressed as traits, because they would
3307// be
3308// recursive. So we need to use template specialization instead.
3309template <typename T>
3310struct handle_self_ref_return {
3311 static T operator()() {
3312 static std::remove_reference_t<T> dummy;
3313 return dummy;
3314 }
3315};
3316template <>
3317struct handle_self_ref_return<void> {
3318 static void operator()() {}
3319};
3320template <>
3321struct handle_self_ref_return<self&> {
3322 static int operator()() { return 0; }
3323};
3324
3325template <typename Concrete, typename T>
3326struct v_table_to_map {
3327 template <typename Sig>
3328 static Sig&& forward(Sig&& sig) {
3329 return std::forward<Sig>(sig);
3330 }
3331};
3332template <typename Concrete>
3333struct v_table_to_map<Concrete, self&> {
3334 template <typename Sig>
3335 static Concrete& forward(Sig&& sig) {
3336 return *unerase_cast<Concrete>(sig);
3337 }
3338};
3339template <typename Concrete>
3340struct v_table_to_map<Concrete, self const&> {
3341 template <typename Sig>
3342 static Concrete const& forward(Sig&& sig) {
3343 return *unerase_cast<Concrete>(sig);
3344 }
3345};
3346
3347template <typename, typename T>
3348struct forward_trait_to_map {
3349 template <typename Sig>
3350 static Sig&& forward(Sig&& sig) {
3351 return std::forward<Sig>(sig);
3352 }
3353};
3354template <typename Traited>
3355struct forward_trait_to_map<Traited, self&> {
3356 template <typename Sig>
3357 static Traited& forward(Sig&& sig) {
3358 return get_proxy_value(std::forward<Sig>(sig));
3359 }
3360};
3361template <typename Traited>
3362struct forward_trait_to_map<Traited, self const&> {
3363 template <typename Sig>
3364 static Traited const& forward(Sig&& sig) {
3365 return get_proxy_value(std::forward<Sig>(sig));
3366 }
3367};
3368//---
3369
3370// --------------------------------------------------------------------------------
3371// any customization traits
3372
3373template <is_proxy Proxy = shared>
3374struct default_proxy {
3375 using type = Proxy;
3376};
3377
3378// --------------------------------------------------------------------------------
3379// typed any
3380
3381template <typename V, is_any Any>
3382struct typed_any : public Any {
3383 using any_t = Any;
3384 using proxy_t = typename any_t::proxy_t;
3385 using proxy_trait_t = any_t::proxy_trait_t;
3386 using void_t = proxy_trait_t::void_t;
3387 static constexpr bool is_const = is_const_void<void_t>;
3388 using value_t = V;
3389
3390 using any_t::any_t;
3391
3392 // cppcheck-suppress-begin noExplicitConstructor
3393 explicit(false) typed_any(V const& v) : any_t(v) {} // NOLINT
3394 explicit(false) typed_any(V&& v) : any_t(std::move(v)) {} // NOLINT
3395 explicit(false) typed_any(any_t i) : any_t(i) { // NOLINT
3396 check_type_match<V>(get_v_table(*this));
3397 }
3398 // cppcheck-suppress-end noExplicitConstructor
3399
3400 value_t const& operator*() const {
3401 return *unchecked_unerase_cast<value_t const>(*this);
3402 }
3403 value_t const* operator->() const {
3404 return unchecked_unerase_cast<value_t const>(*this);
3405 }
3406 value_t const* get() const {
3407 return unchecked_unerase_cast<value_t const>(*this);
3408 }
3409 value_t& operator*() const
3410 requires(!is_const)
3411 {
3412 return *unchecked_unerase_cast<value_t>(*this);
3413 }
3414 value_t* operator->() const
3415 requires(!is_const)
3416 {
3417 return unchecked_unerase_cast<value_t>(*this);
3418 }
3419 value_t* get() const
3420 requires(!is_const)
3421 {
3422 return unchecked_unerase_cast<value_t>(*this);
3423 }
3424 explicit operator bool() const { return static_cast<bool>(this->proxy_); }
3425};
3426
3427template <typename V, is_any Any>
3428auto as(Any source) {
3429 return typed_any<V, Any>{std::move(source)};
3430}
3431
3432template <typename To, typename V, is_any Any>
3433auto as(typed_any<V, Any> source)
3434 requires std::convertible_to<V*, To*>
3435{
3436 if constexpr (typed_any<V, Any>::is_const) {
3437 return typed_any<To const, Any>{std::move(source.proxy_)};
3438 } else {
3439 return typed_any<To, Any>{std::move(source.proxy_)};
3440 }
3441}
3442
3443// --------------------------------------------------------------------------------
3444// any borrow, clone, lock, move
3445
3446template <is_any ToAny, is_proxy FromProxy, typename FromVTable>
3447 requires borrowable_from<typename ToAny::proxy_t, FromProxy, FromVTable>
3448std::expected<ToAny, cast_error> borrow_as(FromProxy const& from,
3449 FromVTable* from_v_table) {
3450 using to = typename ToAny::proxy_t;
3451 return query_v_table<ToAny>(from_v_table).transform([&](auto v_table) {
3452 return ToAny{borrow_as<to>(from, v_table), v_table};
3453 });
3454}
3455
3459template <is_any ToAny, is_any FromAny>
3460 requires borrowable_from<typename ToAny::proxy_t, typename FromAny::proxy_t,
3461 typename FromAny::v_table_t>
3462std::expected<ToAny, cast_error> borrow_as(FromAny const& from) {
3463 if constexpr (std::same_as<typename ToAny::v_table_t,
3464 typename FromAny::v_table_t>) {
3465 return {ToAny{from}};
3466 } else if constexpr (std::derived_from<typename ToAny::v_table_t,
3467 typename FromAny::v_table_t>) {
3468 if (auto to = downcast_to<ToAny>(from)) return *to;
3469 return borrow_as<ToAny>(get_proxy(from), get_v_table(from));
3470 } else {
3471 return borrow_as<ToAny>(get_proxy(from), get_v_table(from));
3472 }
3473}
3474
3477template <is_any ToAny, is_any FromAny>
3478std::expected<ToAny, cast_error> clone_to(FromAny const& from) {
3479 using vv_to_t = typename ToAny::proxy_t;
3480 static_assert(is_proxy<vv_to_t>);
3481 return query_v_table<ToAny>(get_v_table(from)).transform([&](auto v_table) {
3482 return ToAny{clone_to<vv_to_t>(get_proxy(from), v_table), v_table};
3483 });
3484}
3485
3488template <is_any FromAny>
3489 requires std::same_as<typename FromAny::proxy_t, weak>
3490auto lock(FromAny const& from_interface) {
3491 using to_interface_t = FromAny::template type_for<shared>;
3492 static_assert(is_any<to_interface_t>);
3493 using return_t = std::optional<to_interface_t>;
3494 if (auto locked = get_proxy(from_interface).lock())
3495 return return_t{
3496 to_interface_t{std::move(locked), get_v_table(from_interface)}};
3497 return return_t{};
3498}
3499
3503template <is_any ToAny, is_any FromAny>
3504ToAny move_to(FromAny&& from) {
3505 auto to_v_table = query_v_table<ToAny>(from.release_v_table());
3506 return ToAny{move_proxy(std::move(from)), *to_v_table};
3507}
3508
3509// --------------------------------------------------------------------------------
3510// hook
3511
3513template <typename R, typename... Args>
3514class hook;
3515template <typename R, typename... Args>
3516class hook<R(Args...)> {
3517 public:
3518 struct connection_info {
3519 int id;
3520 hook* owner;
3521 };
3522 class connection {
3523 connection_info info_;
3524 friend class hook;
3525
3526 connection(connection const&) = delete;
3527 connection& operator=(connection const&) = delete;
3528
3529 public:
3530 // cppcheck-suppress-begin noExplicitConstructor
3531 explicit(false) connection(connection_info info) : info_(info) {}
3532 // cppcheck-suppress-end noExplicitConstructor
3533 connection& operator=(connection_info info) {
3534 close();
3535 info_ = info;
3536 return *this;
3537 }
3538 connection(connection&&) = default;
3539 connection& operator=(connection&&) = default;
3540 void close() {
3541 if (info_.owner) info_.owner->remove(info_.id);
3542 info_.owner = nullptr;
3543 }
3544
3545 ~connection() { close(); }
3546 };
3547
3548 class super {
3549 int index_;
3550 hook const& hook_;
3551 friend class hook;
3552
3553 super(int index, hook const& hook) : index_(index), hook_(hook) {}
3554
3555 public:
3556 explicit operator bool() const { return index_ >= 0; }
3557 R operator()(Args&&... args) const {
3558 assert(index_ >= 0);
3559 return hook_.callees_[((std::size_t)index_)].second(
3560 super{index_ - 1, hook_}, std::forward<Args>(args)...);
3561 }
3562 };
3563
3564 using callee = std::function<R(super const&, Args...)>;
3565
3566 R operator()(Args&&... args) const {
3567 assert(!callees_.empty());
3568 return callees_.back().second(super{((int)callees_.size()) - 2, *this},
3569 std::forward<Args>(args)...);
3570 }
3571
3572 connection_info insert(callee const& f) {
3573 callees_.emplace_back(entry{next_id_, f});
3574 return connection_info{next_id_++, this};
3575 }
3576
3577 private:
3578 void remove(int id) {
3579 std::erase_if(callees_, [&](auto const id_callee_pair) {
3580 return id_callee_pair.first == id;
3581 });
3582 }
3583
3584 int next_id_ = 0;
3585 using entry = std::pair<int, callee>;
3586 std::vector<entry> callees_;
3587};
3588
3589// --------------------------------------------------------------------------------
3590// factory
3591
3592class unkonwn_factory_key_error : public error {
3593 using error::error;
3594};
3596template <typename Tag>
3597struct key {
3598 const char* label;
3599 friend auto operator<=>(key, key) = default;
3600};
3601template <typename T>
3602struct is_key_impl : std::false_type {};
3603template <typename T>
3604struct is_key_impl<key<T>> : std::true_type {};
3605template <typename T>
3606concept is_key = is_key_impl<T>::value;
3607
3609template <template <typename...> typename Any, typename Key, typename... Args>
3610class factory {
3611 using unique_constructor_t = std::function<Any<unique>(Args...)>;
3612 using shared_const_constructor_t = std::function<Any<shared>(Args...)>;
3613 using val_constructor_t = std::function<Any<val>(Args...)>;
3614 std::map<Key, unique_constructor_t> unique_factory_map_;
3615 std::map<Key, shared_const_constructor_t> shared_factory_map_;
3616 std::map<Key, val_constructor_t> val_factory_map_;
3617
3618 template <is_proxy Proxy>
3619 auto register_impl(auto& map, Key key, auto const& construct) {
3620 map[key] = [construct](Args... args) -> Any<Proxy> {
3621 return Any<Proxy>{std::in_place, construct(std::forward<Args>(args)...)};
3622 };
3623 };
3624
3625 template <is_proxy Proxy>
3626 auto construct_impl(auto const& map, Key key, Args... args) {
3627 if (auto found = map.find(key); found != map.end())
3628 return found->second(std::forward<Args>(args)...);
3629 if constexpr (std::same_as<Key, std::string>) {
3630 throw unkonwn_factory_key_error{key};
3631 } else if constexpr (is_key<Key>) {
3632 throw unkonwn_factory_key_error{key.label};
3633 } else {
3634 throw unkonwn_factory_key_error{std::to_string(key)};
3635 }
3636 };
3637
3638 public:
3639 auto register_(Key const& key, auto const& construct) {
3640 register_impl<unique>(unique_factory_map_, key, construct);
3641 register_impl<shared>(shared_factory_map_, key, construct);
3642 register_impl<val>(val_factory_map_, key, construct);
3643 return nullptr;
3644 }
3645 template <is_proxy Proxy>
3646 auto construct(auto key, Args&&... args) {
3647 if constexpr (std::same_as<Proxy, unique>) {
3648 return construct_impl<Proxy>(unique_factory_map_, key,
3649 std::forward<Args>(args)...);
3650 } else if constexpr (std::same_as<Proxy, shared>) {
3651 static_assert(std::same_as<Proxy, shared>);
3652 return construct_impl<Proxy>(shared_factory_map_, key,
3653 std::forward<Args>(args)...);
3654 } else {
3655 static_assert(std::same_as<Proxy, val>);
3656 return construct_impl<Proxy>(val_factory_map_, key,
3657 std::forward<Args>(args)...);
3658 }
3659 }
3660};
3661
3662// --------------------------------------------------------------------------------
3663// extension member
3664
3665#ifdef ANY_DLL_MODE
3666template <typename InObject>
3667std::size_t& members_count();
3668#else
3669template <typename InObject>
3670std::size_t& members_count() {
3671 static std::size_t count = 0;
3672 return count;
3673}
3674#endif
3675
3677template <typename InObject>
3678struct members {
3679 members() : table_(members_count<InObject>()) {}
3680 using any_value_t = any<val>;
3681 std::vector<any_value_t> table_;
3682 template <typename Member, typename Arg>
3683 void set(Member member, Arg&& arg) {
3684 using value_t = typename Member::value_t;
3685 table_[member.index] =
3686 any_value_t{std::in_place_type<value_t>, std::forward<Arg>(arg)};
3687 }
3688 template <typename Member>
3689 typename Member::value_t const* get(Member member) const {
3690 const auto& val = table_[member.index];
3691 if (!val) return {};
3692 return unchecked_unerase_cast<typename Member::value_t>(val);
3693 }
3694 template <typename Member>
3695 typename Member::value_t* get(Member member) {
3696 auto& val = table_[member.index];
3697 if (!val) return {};
3698 return unchecked_unerase_cast<typename Member::value_t>(val);
3699 }
3700 template <typename Member>
3701 typename Member::value_t& operator[](Member member) {
3702 if (auto val = get(member)) {
3703 return *val;
3704 }
3705 using value_t = typename Member::value_t;
3706 set(member, value_t());
3707 return *get(member);
3708 }
3709};
3710
3711template <typename InObject, typename ValueType>
3712struct member {
3713 using object_t = InObject;
3714 using value_t = ValueType;
3715 std::size_t index = members_count<InObject>()++;
3716};
3717
3718// --------------------------------------------------------------------------------
3719// dispatch
3720
3721#ifdef ANY_DLL_MODE
3722template <typename AnyVTable>
3723std::size_t& dispatchs_count();
3724#else
3726template <typename AnyVTable>
3727std::size_t& dispatchs_count() {
3728 static std::size_t count = 0;
3729 return count;
3730}
3731#endif
3732
3737template <is_any Any>
3738struct virtual_ {
3739 using type = Any;
3740};
3741
3742template <typename Arg>
3743struct translate_erased_function_param {
3744 using type = Arg;
3745};
3746template <is_any Any>
3747struct translate_erased_function_param<virtual_<Any>> {
3748 using type = typename Any::void_t;
3749};
3750
3751template <typename RET, typename... Args>
3752struct translate_erased_function {
3753 using type = RET (*)(typename translate_erased_function_param<Args>::type...);
3754};
3755
3756template <std::size_t I, typename First, typename... Args>
3757auto arg_n(First first, Args... args) {
3758 if constexpr (I == 0) {
3759 return first;
3760 } else {
3761 return arg_n<I - 1>(std::forward<Args>(args)...);
3762 }
3763}
3764
3765template <std::size_t COUNT, typename... Args>
3766constexpr std::size_t dispatch_dimension_count = COUNT;
3767template <std::size_t COUNT, is_any Any, typename... Args>
3768constexpr std::size_t dispatch_dimension_count<COUNT, virtual_<Any>, Args...> =
3769 dispatch_dimension_count<COUNT + 1, Args...>;
3770
3771template <typename R, typename... Classes>
3772struct ensure_function_ptr_from_functor_t {
3773 template <typename FUNCTOR, typename... Args>
3774 struct striped_virtuals {
3775 static R function(Classes&... classes, Args... args) {
3776 return FUNCTOR{}(classes..., args...);
3777 };
3778 };
3779 template <typename FUNCTOR, is_any Any, typename... Args>
3780 struct striped_virtuals<FUNCTOR, virtual_<Any>, Args...>
3781 : striped_virtuals<FUNCTOR, Args...> {};
3782
3783 template <typename... Args>
3784 static auto instance(
3785 auto functor) // if functor is a templated operator() from a
3786 // stateless function object, instantiate it now!;
3787 {
3788 using functor_t = decltype(functor);
3789 if constexpr (std::is_pointer_v<functor_t>) {
3790 return functor;
3791 } else {
3792 return striped_virtuals<functor_t, Args...>::function;
3793 }
3794 }
3795};
3796
3797template <typename... DispatchArgs>
3798struct args_to_tuple {
3799 template <typename T, typename... ActualArgs>
3800 auto operator()(T&& dispatch_args, ActualArgs&&... actual_args) {
3801 return std::tuple_cat(
3802 std::forward<T>(dispatch_args),
3803 std::make_tuple(std::forward<ActualArgs>(actual_args)...));
3804 }
3805};
3806template <is_any Any, typename... DispatchArgs>
3807struct args_to_tuple<virtual_<Any>, DispatchArgs...> {
3808 template <typename T, typename ACTUAL_ARG, typename... ActualArgs>
3809 auto operator()(T&& dispatch_args, ACTUAL_ARG&& dispatch_arg,
3810 ActualArgs&&... actual_args) {
3811 return args_to_tuple<DispatchArgs...>{}(
3812 std::tuple_cat(std::forward<T>(dispatch_args),
3813 std::make_tuple(get_proxy_ptr(dispatch_arg))),
3814 std::forward<ActualArgs>(actual_args)...);
3815 }
3816};
3817
3818template <std::size_t FirstN, typename... Ts>
3819auto get_tuple_head(std::tuple<Ts...> from) {
3820 return [&]<std::size_t... I>(std::index_sequence<I...>) {
3821 return std::make_tuple(std::get<I>(from)...);
3822 }(std::make_index_sequence<FirstN>{});
3823}
3824template <std::size_t FromN, typename... Ts>
3825auto get_tuple_tail(std::tuple<Ts...> from) {
3826 return [&]<std::size_t... I>(std::index_sequence<I...>) {
3827 return std::make_tuple(std::get<I>(from)...);
3828 }(std::make_index_sequence<std::tuple_size_v<std::tuple<Ts...>> - FromN>{});
3829}
3830
3831template <typename R, typename... FArgs>
3832struct dispatch_function;
3833template <typename R, typename... FArgs>
3834struct dispatch_function<R, std::tuple<FArgs...>> {
3835 using type = R (*)(FArgs...);
3836};
3837
3838class no_default_function_error : public error {
3839 using error::error;
3840};
3841
3842template <typename R, typename... OuterArgs>
3843struct dispatch_function_types {
3844 template <is_any... Anys>
3845 struct inner {
3846 template <typename... Args>
3847 struct implemenation {
3848 struct type {
3849 using function_t = hook<R(Anys const&..., Args...)>;
3850 static auto function() {
3851 return []([[maybe_unused]] auto super,
3852 [[maybe_unused]] Anys const&... anys,
3853 [[maybe_unused]] Args... args) -> R {
3854 if constexpr (std::same_as<R, void>) {
3855 return;
3856 } else {
3857 if constexpr (std::is_default_constructible_v<R>) {
3858 return R{};
3859 } else {
3860 throw no_default_function_error("no default function");
3861 }
3862 }
3863 };
3864 }
3865 };
3866 };
3867 template <is_any Any, typename... Args>
3868 struct implemenation<virtual_<Any>, Args...> : implemenation<Args...> {};
3869 template <typename... Args>
3870 using type = typename implemenation<Args...>::type;
3871 };
3872
3873 template <typename... Args>
3874 struct outer {
3875 template <is_any... Anys>
3876 using type = inner<Anys...>::template type<Args...>;
3877 };
3878 template <is_any Any, typename... Args>
3879 struct outer<virtual_<Any>, Args...> {
3880 template <is_any... Anys>
3881 using type = outer<Args...>::template type<Any, Anys...>;
3882 };
3883
3884 using default_type = outer<OuterArgs...>::template type<>;
3885};
3886
3887template <typename F, typename... Args>
3888struct dispatch_matrix {
3889 using type = F;
3890};
3891template <typename DispatchMatrix, is_any Any, typename... Args>
3892struct dispatch_matrix<DispatchMatrix, virtual_<Any>, Args...> {
3893 using type =
3894 typename dispatch_matrix<std::vector<DispatchMatrix>, Args...>::type;
3895};
3896
3903template <typename R, typename... Args>
3926template <typename R, typename... Args>
3927class dispatch<R(Args...)> {
3928 public:
3929 using erased_function_t =
3930 typename translate_erased_function<R, Args...>::type;
3931
3932 static constexpr std::size_t dimension_count =
3933 dispatch_dimension_count<0, Args...>;
3934
3935 using dispatch_matrix_t = dispatch_matrix<erased_function_t, Args...>::type;
3936 dispatch_matrix_t dispatch_matrix_;
3937
3938 using default_ = typename dispatch_function_types<R, Args...>::default_type;
3939 default_::function_t dispatch_default_hook_;
3940 default_::function_t::connection default_connection_ =
3941 dispatch_default_hook_.insert(default_::function());
3942
3943 enum class kind { single, multiple };
3944 template <kind Kind, std::size_t Dimension, typename... DispatchArgs>
3945 struct dispatch_access;
3946
3947 template <typename... DispatchArgs>
3948 struct dispatch_access<kind::multiple, dimension_count, DispatchArgs...> {
3949 auto define(auto fp, auto& matrix) {
3950 matrix = reinterpret_cast<erased_function_t>(fp);
3951 return fp;
3952 }
3953 template <typename F, typename ArgsTuple>
3954 std::optional<R> invoke(F const& target, ArgsTuple&& dispatch_args_tuple,
3955 auto&&...) const {
3956 if (!target) return {};
3957 auto typed_target = reinterpret_cast<
3958 typename dispatch_function<R, std::decay_t<ArgsTuple>>::type>(target);
3959 return std::apply(typed_target,
3960 std::forward<ArgsTuple>(dispatch_args_tuple));
3961 }
3962 };
3963
3964 template <std::size_t Dimension, is_any Any, typename... DispatchArgs>
3965 struct dispatch_access<kind::multiple, Dimension, virtual_<Any>,
3966 DispatchArgs...>
3967 : dispatch_access<kind::multiple, Dimension + 1, DispatchArgs...> {
3968 using interface_t = Any;
3969 using v_table_t = typename interface_t::v_table_t;
3970 using next_t =
3971 dispatch_access<kind::multiple, Dimension + 1, DispatchArgs...>;
3972
3973 // index 0 is for the 'wildcard' functions
3974 std::size_t index_ = 1 + dispatchs_count<v_table_t>()++;
3975 std::size_t dispatch_dimension_size_ = 1;
3976
3977 template <typename Class>
3978 std::size_t get_dispatch_index() {
3979 if constexpr (std::same_as<Any, Class>) {
3980 return 0;
3981 } else {
3982 auto dispatch_table = dispatch_table_instance<v_table_t, Class>();
3983 if (auto index = get_multi_dispatch_index_at(dispatch_table, index_))
3984 return index;
3985 else
3986 set_multi_dispatch_index_at(dispatch_table, index_,
3987 dispatch_dimension_size_);
3988 return dispatch_dimension_size_++;
3989 }
3990 }
3991
3992 template <typename Class, typename... Classes>
3993 auto define(auto fp, auto& matrix) {
3994 auto dispatch_index = get_dispatch_index<Class>();
3995 if (matrix.size() <= dispatch_index) matrix.resize(dispatch_index + 1);
3996 return next_t::template define<Classes...>(fp, matrix[dispatch_index]);
3997 }
3998
3999 template <typename DispatchMatrix, typename ArgsTuple,
4000 typename... ActualArgs>
4001 std::optional<R> invoke(DispatchMatrix const& target,
4002 ArgsTuple&& dispatch_args_tuple, Any const& any,
4003 ActualArgs&&... actual_args) const {
4004 auto dispatch_table = get_v_table(any)->dispatch_table;
4005 auto dispatch_dim = get_multi_dispatch_index_at(dispatch_table, index_);
4006 if (dispatch_dim && target.size() > dispatch_dim)
4007 if (auto found =
4008 next_t::invoke(target[dispatch_dim],
4009 std::forward<ArgsTuple>(dispatch_args_tuple),
4010 std::forward<ActualArgs>(actual_args)...))
4011 return found;
4012
4013 if (target.size())
4014 return next_t::invoke(
4015 target[0],
4016 std::tuple_cat(get_tuple_head<Dimension>(dispatch_args_tuple),
4017 std::make_tuple(&any),
4018 get_tuple_tail<Dimension + 1>(dispatch_args_tuple)),
4019 std::forward<ActualArgs>(actual_args)...);
4020 return {};
4021 }
4022 };
4023
4024 template <is_any Any, typename... AccessArgs>
4025 struct dispatch_access<kind::single, 0, virtual_<Any>, AccessArgs...> {
4026 using interface_t = Any;
4027 using v_table_t = typename interface_t::v_table_t;
4028 std::size_t index_ = dispatchs_count<v_table_t>()++;
4029
4030 template <typename CLASS>
4031 auto define(auto fp, auto&) {
4032 auto v_table = dispatch_table_instance<v_table_t, CLASS>();
4033 insert_function(v_table, index_, fp);
4034 return fp;
4035 }
4036
4037 template <typename... Other>
4038 R invoke(default_::function_t const& default_, Any const& any,
4039 Other&&... other) const {
4040 auto v_table = get_v_table(any)->dispatch_table;
4041 auto target = get_function(v_table, index_);
4042 if (!target)
4043 return std::invoke(default_, any, std::forward<Other>(other)...);
4044 auto erased_function = reinterpret_cast<erased_function_t>(target);
4045 return std::invoke(erased_function, get_proxy_ptr(any),
4046 std::forward<Other>(other)...);
4047 }
4048 };
4049
4050 static const constexpr kind dispatch_kind =
4051 (dimension_count > 1) ? kind::multiple : kind::single;
4052 dispatch_access<dispatch_kind, 0, Args...> dispatch_access_;
4053
4054 public:
4061 template <typename... Classes>
4062 auto define(auto f) {
4063 auto fp = ensure_function_ptr_from_functor_t<
4064 R, Classes...>::template instance<Args...>(f);
4065 return dispatch_access_.template define<Classes...>(fp, dispatch_matrix_);
4066 };
4067
4074 template <typename... ActualArgs>
4075 auto operator()(ActualArgs&&... actual_args) const {
4076 if constexpr (dispatch_kind == kind::multiple) {
4077 auto dispatch_args_tuple = args_to_tuple<Args...>{}(
4078 std::tuple<>{}, std::forward<ActualArgs>(actual_args)...);
4079 return *dispatch_access_
4080 .invoke(dispatch_matrix_, dispatch_args_tuple,
4081 std::forward<ActualArgs>(actual_args)...)
4082 .or_else([&]() -> std::optional<R> {
4083 return std::invoke(
4084 dispatch_default_hook_,
4085 std::forward<ActualArgs>(actual_args)...);
4086 });
4087 } else {
4088 return dispatch_access_.invoke(dispatch_default_hook_,
4089 std::forward<ActualArgs>(actual_args)...);
4090 }
4091 }
4092 auto& get_dispatch_default_hook() { return dispatch_default_hook_; };
4093};
4094
4095template <size_t At, typename Tuple, size_t... Is>
4096auto make_tuple_from_elements(Tuple&& tuple, std::index_sequence<Is...>) {
4097 return std::forward_as_tuple(
4098 std::get<Is + At>(std::forward<Tuple>(tuple))...);
4099}
4100template <size_t At, size_t N, typename Tuple>
4101auto make_tuple_from_elements_at(Tuple&& tuple) {
4102 return make_tuple_from_elements<At>(std::forward<Tuple>(tuple),
4103 std::make_index_sequence<N>{});
4104}
4105
4106template <typename Vany, typename DynamicDispatch, auto StaticDispatch>
4107class dispatch_vany {
4108 DynamicDispatch dynamic_dispatch_;
4109 constexpr static const std::size_t dimension_count =
4110 DynamicDispatch::dimension_count;
4111
4112 template <typename Vany1, typename... Args>
4113 auto invoke1(Vany1&& vany, Args&&... args) const {
4114 return std::visit(
4115 [&]<typename TypedArg>([[maybe_unused]] TypedArg&& arg) {
4116 return overloads{
4117 StaticDispatch,
4118 [&]<is_any Any, typename... Vargs>(Any&& any, Vargs&&... vargs) {
4119 return dynamic_dispatch_(std::forward<Any>(any),
4120 std::forward<Vargs>(vargs)...);
4121 }}(std::forward<TypedArg>(arg), std::forward<Args>(args)...);
4122 },
4123 get_proxy_value(std::forward<Vany1>(vany)));
4124 }
4125
4126 template <is_any Vany1, is_any Vany2, typename... Args>
4127 auto invoke2(Vany1&& vany1, Vany2&& vany2, Args&&... args) const {
4128 using vany1_t = std::decay_t<Vany1>;
4129 using vany2_t = std::decay_t<Vany2>;
4130 using cv1_t = anyxx::vany_type_trait<vany1_t>::concrete_variant;
4131 using any_v1 = anyxx::vany_type_trait<vany1_t>::any_in_variant;
4132 using cv2_t = anyxx::vany_type_trait<vany2_t>::concrete_variant;
4133 using any_v2 = anyxx::vany_type_trait<vany2_t>::any_in_variant;
4134
4135 auto dispatch_combined = [&]<typename DA1, typename DA2>(DA1&& da1,
4136 DA2&& da2) {
4137 auto dyn_case1 = [&]<is_any A1, is_any A2, typename... VAs>(
4138 A1&& a1, A2&& a2, VAs&&... vas) {
4139 return dynamic_dispatch_(std::forward<A1>(a1), std::forward<A2>(a2),
4140 std::forward<VAs>(vas)...);
4141 };
4142 auto dyn_case2 = [&]<is_any A1, typename A2, typename... VAs>(
4143 A1&& a1, A2 a2, VAs&&... vas)
4144 requires std::constructible_from<cv2_t, A2>
4145 {
4146 return dynamic_dispatch_(std::forward<A1>(a1),
4147 any_v2{std::in_place, cv2_t{std::move(a2)}},
4148 std::forward<VAs>(vas)...);
4149 };
4150 auto dyn_case3 = [&]<typename A1, is_any A2, typename... VAs>(
4151 A1 a1, A2&& a2, VAs&&... vas)
4152 requires std::constructible_from<cv1_t, A1>
4153 {
4154 return dynamic_dispatch_(any_v1{std::in_place, cv1_t{std::move(a1)}},
4155 std::forward<A2>(a2),
4156 std::forward<VAs>(vas)...);
4157 };
4158 auto dyn_case4 = [&]<typename A1, typename A2, typename... VAs>(
4159 A1 a1, A2 a2, VAs&&... vas)
4160 requires(std::constructible_from<cv1_t, A1> &&
4161 std::constructible_from<cv2_t, A2>)
4162 {
4163 return dynamic_dispatch_(any_v1{std::in_place, cv1_t{std::move(a1)}},
4164 any_v2{std::in_place, cv2_t{std::move(a2)}},
4165 std::forward<VAs>(vas)...);
4166 };
4167 return overloads{StaticDispatch, dyn_case1, dyn_case2, dyn_case3,
4168 dyn_case4}(std::forward<DA1>(da1),
4169 std::forward<DA2>(da2),
4170 std::forward<Args>(args)...);
4171 };
4172
4173 return std::visit(dispatch_combined,
4174 get_proxy_value(std::forward<Vany1>(vany1)),
4175 get_proxy_value(std::forward<Vany2>(vany2)));
4176 }
4177
4178 public:
4179 template <typename... Classes>
4180 auto define(auto f) {
4181 return dynamic_dispatch_.template define<Classes...>(f);
4182 }
4183
4184 template <typename... Args>
4185 auto operator()(Args&&... args) const {
4186 if constexpr (dimension_count == 1) {
4187 return invoke1(std::forward<Args>(args)...);
4188 } else {
4189 if constexpr (dimension_count == 2) {
4190 return invoke2(std::forward<Args>(args)...);
4191 } else {
4192 static_assert(dimension_count <= 2,
4193 "dispatch_vany only supports one and two dimensions");
4194 }
4195 }
4196 }
4197};
4198} // namespace anyxx
4199
4200#define ANY_MERGE_(a, b) a##b
4201#define ANY_LABEL_(a) ANY_MERGE_(unique_name_, a)
4202#define ANY_UNIQUE_NAME_ ANY_LABEL_(__COUNTER__)
4203#define ANY_UNIQUE_NAME ANY_UNIQUE_NAME_
4204#define __ ANY_UNIQUE_NAME_
4205
4216
4224#define ANY_SINGLETON_DECLARE(export_, name, ...) \
4225 using name##_t = __VA_ARGS__; \
4226 export_ extern name##_t& get_##name(); \
4227 static inline name##_t& name = get_##name();
4228
4235#define ANY_SINGLETON(namespace_, name, ...) \
4236 namespace_::name##_t& namespace_::get_##name() { \
4237 static name##_t singleton_{__VA_ARGS__}; \
4238 return singleton_; \
4239 };
4240
4241
4246
4256#define VANY_DISPACH_DECLARE(export_, name, vany, signature, static_dispatch) \
4257 constexpr static inline auto name##_static_dispatch = \
4258 anyxx::overloads{_detail_REMOVE_PARENS(static_dispatch)}; \
4259 \
4260 using name##_vany = vany; \
4261 using name##_dynamic_dispatch = \
4262 anyxx::dispatch<_detail_REMOVE_PARENS(signature)>; \
4263 \
4264 ANY_SINGLETON_DECLARE( \
4265 , name, \
4266 anyxx::dispatch_vany<name##_vany, name##_dynamic_dispatch, \
4267 name##_static_dispatch>)
4268
4274#define VANY_DISPACH(namespace_, name) ANY_SINGLETON(namespace_, name);
4276
4277#ifdef ANY_DLL_MODE
4278
4279#define ANY_META_CLASS_FWD(export_, ...) \
4280 template <> \
4281 export_ anyxx::meta_data& anyxx::get_meta_data<__VA_ARGS__>();
4282
4283#define ANY_META_CLASS(...) \
4284 template <> \
4285 anyxx::meta_data& anyxx::get_meta_data<std::decay_t<__VA_ARGS__>>() { \
4286 return runtime_implementation<__VA_ARGS__>(); \
4287 }
4288
4289#else
4290
4295
4301#define ANY_META_CLASS_FWD(...)
4306#define ANY_META_CLASS(...)
4307
4308#endif
4309
4310#define ANY_META_CLASS_STATIC(...) \
4311 ANY_META_CLASS_FWD(, __VA_ARGS__) \
4312 ANY_META_CLASS(__VA_ARGS__)
4313
4323#define ANY_REGISTER_MODEL(class_, interface_, ...) \
4324 namespace { \
4325 static auto __ = anyxx::bind_v_table_to_meta_data< \
4326 interface_##_v_table _detail_ANYXX_OPTIONAL_TEMPLATE_ARGS(__VA_ARGS__), \
4327 ANYXX_UNPAREN(class_)>(); \
4328 }
4329
4331
4332#ifdef ANY_DLL_MODE
4333
4334#define ANY_MEMBERS_COUNT_FWD(export_, ns_, c_) \
4335 namespace ns_ { \
4336 struct c_; \
4337 } \
4338 namespace anyxx { \
4339 template <> \
4340 export_ std::size_t& members_count<ns_::c_>(); \
4341 }
4342
4343#define ANY_MEMBERS_COUNT_IMPL(ns_, c_) \
4344 template <> \
4345 std::size_t& anyxx::members_count<ns_::c_>() { \
4346 static std::size_t count = 0; \
4347 return count; \
4348 }
4349
4350#define ANY_MEMBER_FWD(export_, object_, member_, type_) \
4351 export_ anyxx::member<object_, type_>& _inintialize_##member_(); \
4352 inline const anyxx::member<object_, type_>& member_ = \
4353 _inintialize_##member_();
4354
4355#define ANY_MEMBER_IMPL(ns_, object_, member_, type_) \
4356 anyxx::member<object_, type_>& ns_::_inintialize_##member_() { \
4357 static anyxx::member<object_, type_> instance; \
4358 return instance; \
4359 }
4360
4361#else
4362
4363#define ANY_MEMBERS_COUNT_FWD(...)
4364#define ANY_MEMBERS_COUNT_IMPL(...)
4365#define ANY_MEMBER_FWD(...)
4366#define ANY_MEMBER_IMPL(...)
4367
4368#endif
4369
4370#ifdef ANY_DLL_MODE
4371
4372#define ANY_DISPATCH_COUNT_FWD(export_, ns_, any_) \
4373 namespace ns_ {} \
4374 namespace anyxx { \
4375 template <> \
4376 export_ std::size_t& dispatchs_count<ns_::any_##_v_table>(); \
4377 }
4378
4379#define ANY_DISPATCH_COUNT(ns_, any_) \
4380 template <> \
4381 std::size_t& anyxx::dispatchs_count<ns_::any_##_v_table>() { \
4382 static std::size_t count = 0; \
4383 return count; \
4384 }
4385
4386#define ANY_DISPATCH_FOR_FWD(export_, class_, interface_namespace_, \
4387 interface_) \
4388 namespace anyxx { \
4389 template <> \
4390 export_ dispatch_table_t* dispatch_table_instance< \
4391 interface_namespace_::interface_##_v_table, class_>(); \
4392 }
4393
4394#define ANY_DISPATCH_FOR(class_, interface_namespace_, interface_) \
4395 template <> \
4396 anyxx::dispatch_table_t* anyxx::dispatch_table_instance< \
4397 interface_namespace_::interface_##_v_table, class_>() { \
4398 return dispatch_table_instance_implementation< \
4399 interface_namespace_::interface_##_v_table, class_>(); \
4400 }
4401
4402#else
4403
4421
4428#define ANY_DISPATCH_COUNT_FWD(...)
4434#define ANY_DISPATCH_COUNT(...)
4442#define ANY_DISPATCH_FOR_FWD(...)
4449#define ANY_DISPATCH_FOR(...)
4450
4452
4453#endif
4454
4467
any< using_< Type >, Trait > use_as
Definition anyxx.hpp:3132
Any< using_< vany_variant< Any, Proxy, Types... > > > make_vany
A factory type to direct get the any for the vany.
Definition anyxx.hpp:1784
any< trait_class< Type >, Trait > any_trait_class
Definition anyxx.hpp:3163
any< using_< Type >, Trait< Ts... > > use_as_
Definition anyxx.hpp:3137
auto trait_as(T &&v)
Definition anyxx.hpp:3143
std::size_t & dispatchs_count()
A counter for dispatch tables per v-table type.
Definition anyxx.hpp:3727
The core class template to control dispatch for external polymorphism.
Definition anyxx.hpp:2806
any(std::in_place_type_t< T >, Args &&... args)
Definition anyxx.hpp:2872
any(std::in_place_t, V &&v)
Definition anyxx.hpp:2860
auto define(auto f)
Register a dispatch target for the model provided in the type parameter.
Definition anyxx.hpp:4062
auto operator()(ActualArgs &&... actual_args) const
Invoke the dispatch.
Definition anyxx.hpp:4075
Open dispatch method. Solves the expression problem. See dispatch<R(Args...)> for details.
Definition anyxx.hpp:3904
A class template to implement a factory for any objects.
Definition anyxx.hpp:3610
A class template to implement a hook/callback chain.
Definition anyxx.hpp:3514
Requirements for a trait type.
Definition anyxx.hpp:1535
Requirements for a dynamic (i.e., type-erased) Proxy.
Definition anyxx.hpp:1543
Requirements for a proxy type.
Definition anyxx.hpp:1491
std::optional< To > downcast_to(From from)
Safe downcast to a derived trait using runtime information from the v-Tables.
Definition anyxx.hpp:3074
auto lock(FromAny const &from_interface)
Lock a shared any.
Definition anyxx.hpp:3490
#define ANY_MODEL_MAP(model_, trait_)
ANY_MODEL_MAP macro.
Definition anyxx.hpp:1192
#define TRAIT_TYPE(Name, T, Trait,...)
translates to the type defined in the model map of a trait. This is useful for associated types,...
Definition anyxx.hpp:1182
observer< const_void > cref
Definition anyxx.hpp:1863
std::shared_ptr< void const > shared
Definition anyxx.hpp:2033
observer< mutable_void > mutref
Definition anyxx.hpp:1867
std::weak_ptr< void const > weak
Definition anyxx.hpp:2037
std::variant< Any< Proxy >, Types... > vany_variant
Definition anyxx.hpp:1780
#define ANY_TYPE(...)
Dependent type definition in a TRAIT. This is useful for defining associated types,...
Definition anyxx.hpp:1146
#define TRAIT_EX(n,...)
TRAIT with decoration.
Definition anyxx.hpp:782
Basic lifetime functionality.
Definition anyxx.hpp:1368
any_v_table(std::in_place_type_t< Concrete > concrete)
Type-erasing constructor.
Definition anyxx.hpp:1374
A key type for factory registration.
Definition anyxx.hpp:3597
observeable_rtti_v_table(std::in_place_type_t< Concrete > concrete)
Type-erasing constructor.
Definition anyxx.hpp:1335
Definition anyxx.hpp:1316
observeable_v_table(std::in_place_type_t< Concrete > concrete)
Type-erasing constructor.
Definition anyxx.hpp:1321
Definition anyxx.hpp:3153
Use this type to indicate, that the ANY_TYPE must be specified in the model map.
Definition anyxx.hpp:1309
Definition anyxx.hpp:1947
Definition anyxx.hpp:3116
any< using_< Value >, Trait > as
Definition anyxx.hpp:3126
A tag to indicate that the corresponding function parameter is an any used for dispatch.
Definition anyxx.hpp:3738
Proxy to manage the captured object as value with small object optimization.
Definition anyxx.hpp:2189