1 #ifndef META_FACTORY_HPP 2 #define META_FACTORY_HPP 11 #include <type_traits> 29 struct function_helper;
32 template<
typename Ret,
typename... Args>
33 struct function_helper<Ret(Args...)> {
34 using return_type = std::remove_cv_t<std::remove_reference_t<Ret>>;
35 using args_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
37 static constexpr
auto size =
sizeof...(Args);
38 static constexpr
auto is_const =
false;
40 static auto arg(
typename internal::func_node::size_type index) noexcept {
41 return std::array<type_node *,
sizeof...(Args)>{{type_info<Args>::resolve()...}}[index];
46 template<
typename Ret,
typename... Args>
47 struct function_helper<Ret(Args...) const>: function_helper<Ret(Args...)> {
48 static constexpr
auto is_const =
true;
52 template<
typename Ret,
typename... Args,
typename Class>
53 constexpr function_helper<Ret(Args...)>
54 to_function_helper(Ret(Class:: *)(Args...));
57 template<
typename Ret,
typename... Args,
typename Class>
58 constexpr function_helper<Ret(Args...)
const>
59 to_function_helper(Ret(Class:: *)(Args...)
const);
62 template<
typename Ret,
typename... Args>
63 constexpr function_helper<Ret(Args...)>
64 to_function_helper(Ret(*)(Args...));
67 constexpr
void to_function_helper(...);
70 template<
typename Cand
idate>
71 using function_helper_t = decltype(to_function_helper(std::declval<Candidate>()));
74 template<
typename Type,
typename... Args, std::size_t... Indexes>
75 any construct(
any *
const args, std::index_sequence<Indexes...>) {
76 [[maybe_unused]]
auto direct = std::make_tuple((args+Indexes)->try_cast<Args>()...);
79 if(((std::get<Indexes>(direct) || (args+Indexes)->convert<Args>()) && ...)) {
80 any = Type{(std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<Args>())...};
87 template<
bool Const,
typename Type, auto Data>
88 bool setter([[maybe_unused]]
handle handle, [[maybe_unused]]
any index, [[maybe_unused]]
any value) {
89 bool accepted =
false;
91 if constexpr(!Const) {
92 if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
93 using helper_type = function_helper_t<decltype(Data)>;
94 using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>,
typename helper_type::args_type>;
95 static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
97 auto *direct = value.try_cast<data_type>();
99 if(clazz && (direct || value.convert<data_type>())) {
100 std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
103 }
else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
104 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
105 static_assert(std::is_invocable_v<decltype(Data), Type *>);
108 if constexpr(std::is_array_v<data_type>) {
109 using underlying_type = std::remove_extent_t<data_type>;
110 auto *direct = value.try_cast<underlying_type>();
111 auto *idx = index.try_cast<std::size_t>();
113 if(clazz && idx && (direct || value.convert<underlying_type>())) {
114 std::invoke(Data, clazz)[*idx] = direct ? *direct : value.cast<underlying_type>();
118 auto *direct = value.try_cast<data_type>();
120 if(clazz && (direct || value.convert<data_type>())) {
121 std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
126 static_assert(std::is_pointer_v<decltype(Data)>);
127 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*Data)>>;
129 if constexpr(std::is_array_v<data_type>) {
130 using underlying_type = std::remove_extent_t<data_type>;
131 auto *direct = value.try_cast<underlying_type>();
132 auto *idx = index.try_cast<std::size_t>();
134 if(idx && (direct || value.convert<underlying_type>())) {
135 (*Data)[*idx] = (direct ? *direct : value.cast<underlying_type>());
139 auto *direct = value.try_cast<data_type>();
141 if(direct || value.convert<data_type>()) {
142 *Data = (direct ? *direct : value.cast<data_type>());
153 template<
typename Type, auto Data,
typename Policy>
154 any getter([[maybe_unused]] handle handle, [[maybe_unused]]
any index) {
155 auto dispatch = [](
auto &&value) {
156 if constexpr(std::is_same_v<Policy, as_void_t>) {
157 return any{std::in_place_type<void>};
158 }
else if constexpr(std::is_same_v<Policy, as_alias_t>) {
159 return any{std::ref(std::forward<decltype(value)>(value))};
161 static_assert(std::is_same_v<Policy, as_is_t>);
162 return any{std::forward<decltype(value)>(value)};
166 if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
167 static_assert(std::is_invocable_v<decltype(Data), Type &>);
169 return clazz ? dispatch(std::invoke(Data, *clazz)) :
any{};
170 }
else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
171 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
172 static_assert(std::is_invocable_v<decltype(Data), Type *>);
175 if constexpr(std::is_array_v<data_type>) {
176 auto *idx = index.try_cast<std::size_t>();
177 return (clazz && idx) ? dispatch(std::invoke(Data, clazz)[*idx]) :
any{};
179 return clazz ? dispatch(std::invoke(Data, clazz)) :
any{};
182 static_assert(std::is_pointer_v<std::decay_t<decltype(Data)>>);
184 if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
185 auto *idx = index.try_cast<std::size_t>();
186 return idx ? dispatch((*Data)[*idx]) :
any{};
188 return dispatch(*Data);
194 template<
typename Type,
auto Candidate,
typename Policy, std::size_t... Indexes>
195 any invoke([[maybe_unused]] handle handle,
any *args, std::index_sequence<Indexes...>) {
196 using helper_type = function_helper_t<decltype(Candidate)>;
198 auto dispatch = [](
auto *... args) {
199 if constexpr(std::is_void_v<typename helper_type::return_type> || std::is_same_v<Policy, as_void_t>) {
200 std::invoke(Candidate, *args...);
201 return any{std::in_place_type<void>};
202 }
else if constexpr(std::is_same_v<Policy, as_alias_t>) {
203 return any{std::ref(std::invoke(Candidate, *args...))};
205 static_assert(std::is_same_v<Policy, as_is_t>);
206 return any{std::invoke(Candidate, *args...)};
210 [[maybe_unused]]
const auto direct = std::make_tuple([](
meta::any *
any,
auto *instance) {
211 using arg_type = std::remove_reference_t<decltype(*instance)>;
213 if(!instance && any->
convert<arg_type>()) {
214 instance = any->try_cast<arg_type>();
218 }(args+Indexes, (args+Indexes)->try_cast<std::tuple_element_t<Indexes, typename helper_type::args_type>>())...);
220 if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Candidate)>>) {
221 return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : any{};
223 auto *clazz = any{handle}.
try_cast<Type>();
224 return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : any{};
248 template<
typename Type>
250 template<
typename Node>
251 bool duplicate(
const std::size_t identifier,
const Node *node) noexcept {
252 return node && (node->identifier == identifier || duplicate(identifier, node->next));
255 bool duplicate(
const any &key,
const internal::prop_node *node) noexcept {
256 return node && (node->key() == key || duplicate(key, node->next));
260 internal::prop_node * properties() {
264 template<
typename Owner,
typename Property,
typename... Other>
265 internal::prop_node * properties(Property &&property, Other &&... other) {
266 static std::remove_cv_t<std::remove_reference_t<Property>>
prop{};
268 static internal::prop_node node{
271 return std::as_const(std::get<0>(
prop));
274 return std::as_const(std::get<1>(
prop));
281 prop = std::forward<Property>(property);
282 node.next = properties<Owner>(std::forward<Other>(other)...);
283 assert(!duplicate(
any{std::get<0>(
prop)}, node.next));
287 void unregister_prop(internal::prop_node **
prop) {
291 node->next =
nullptr;
295 void unregister_dtor() {
296 if(
auto node = internal::type_info<Type>::type->
dtor; node) {
297 internal::type_info<Type>::type->dtor =
nullptr;
298 *node->underlying =
nullptr;
302 template<auto Member>
303 auto unregister_all(
int)
304 -> decltype((internal::type_info<Type>::type->*Member)->prop,
void()) {
305 while(internal::type_info<Type>::type->*Member) {
306 auto node = internal::type_info<Type>::type->*Member;
307 internal::type_info<Type>::type->*Member = node->next;
308 unregister_prop(&node->prop);
309 node->next =
nullptr;
310 *node->underlying =
nullptr;
314 template<auto Member>
315 void unregister_all(
char) {
316 while(internal::type_info<Type>::type->*Member) {
317 auto node = internal::type_info<Type>::type->*Member;
318 internal::type_info<Type>::type->*Member = node->next;
319 node->next =
nullptr;
320 *node->underlying =
nullptr;
335 template<
typename... Property>
336 factory type(
const std::size_t identifier, Property &&... property) noexcept {
337 assert(!internal::type_info<Type>::type);
338 auto *node = internal::type_info<Type>::resolve();
339 node->identifier = identifier;
340 node->next = internal::type_info<>::type;
341 node->prop = properties<Type>(std::forward<Property>(property)...);
342 assert(!duplicate(node->identifier, node->next));
343 internal::type_info<Type>::type = node;
344 internal::type_info<>::type = node;
357 template<
typename Base>
359 static_assert(std::is_base_of_v<Base, Type>);
360 auto *
const type = internal::type_info<Type>::resolve();
362 static internal::base_node node{
363 &internal::type_info<Type>::template
base<Base>,
366 &internal::type_info<Base>::resolve,
367 [](
void *instance) noexcept ->
void * {
368 return static_cast<Base *
>(
static_cast<Type *
>(instance));
376 assert((!internal::type_info<Type>::template
base<Base>));
377 internal::type_info<Type>::template base<Base> = &node;
392 template<
typename To>
394 static_assert(std::is_convertible_v<Type, To>);
395 auto *
const type = internal::type_info<Type>::resolve();
397 static internal::conv_node node{
398 &internal::type_info<Type>::template
conv<To>,
401 &internal::type_info<To>::resolve,
402 [](
const void *instance) ->
any {
403 return static_cast<To
>(*
static_cast<const Type *
>(instance));
411 assert((!internal::type_info<Type>::template
conv<To>));
412 internal::type_info<Type>::template conv<To> = &node;
430 template<auto Cand
idate>
432 using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
433 auto *
const type = internal::type_info<Type>::resolve();
435 static internal::conv_node node{
439 &internal::type_info<conv_type>::resolve,
440 [](
const void *instance) ->
any {
441 return std::invoke(Candidate, *static_cast<const Type *>(instance));
450 internal::type_info<Type>::template conv<conv_type> = &node;
471 template<
auto Func,
typename Policy =
as_is_t,
typename... Property>
473 using helper_type = internal::function_helper_t<decltype(Func)>;
474 static_assert(std::is_same_v<typename helper_type::return_type, Type>);
475 auto *
const type = internal::type_info<Type>::resolve();
477 static internal::ctor_node node{
485 return internal::invoke<Type, Func, Policy>({},
any, std::make_index_sequence<helper_type::size>{});
493 node.prop = properties<typename helper_type::args_type>(std::forward<Property>(property)...);
495 internal::type_info<Type>::template ctor<typename helper_type::args_type> = &node;
513 template<
typename... Args,
typename... Property>
515 using helper_type = internal::function_helper_t<Type(*)(Args...)>;
516 auto *
const type = internal::type_info<Type>::resolve();
518 static internal::ctor_node node{
526 return internal::construct<Type, std::remove_cv_t<std::remove_reference_t<Args>>...>(
any, std::make_index_sequence<helper_type::size>{});
534 node.prop = properties<typename helper_type::args_type>(std::forward<Property>(property)...);
536 internal::type_info<Type>::template ctor<typename helper_type::args_type> = &node;
560 static_assert(std::is_invocable_v<decltype(Func), Type &>);
561 auto *
const type = internal::type_info<Type>::resolve();
563 static internal::dtor_node node{
564 &internal::type_info<Type>::template
dtor<Func>,
567 const auto valid = (
handle.
type() == internal::type_info<Type>::resolve()->clazz());
570 std::invoke(Func, *
any{
handle}.try_cast<Type>());
580 assert(!internal::type_info<Type>::type->
dtor);
581 assert((!internal::type_info<Type>::template
dtor<Func>));
582 internal::type_info<Type>::template dtor<Func> = &node;
583 internal::type_info<Type>::type->dtor = &node;
603 template<
auto Data,
typename Policy =
as_is_t,
typename... Property>
604 factory data(
const std::size_t identifier, Property &&... property) noexcept {
605 auto *
const type = internal::type_info<Type>::resolve();
606 internal::data_node *curr =
nullptr;
608 if constexpr(std::is_same_v<Type, decltype(Data)>) {
609 static_assert(std::is_same_v<Policy, as_is_t>);
611 static internal::data_node node{
612 &internal::type_info<Type>::template
data<Data>,
619 &internal::type_info<Type>::resolve,
621 [](handle, any) -> any {
return Data; },
627 node.
prop = properties<std::integral_constant<Type, Data>>(std::forward<Property>(property)...);
629 }
else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
630 using data_type = std::remove_reference_t<decltype(std::declval<Type>().*Data)>;
632 static internal::data_node node{
633 &internal::type_info<Type>::template
data<Data>,
638 std::is_const_v<data_type>,
639 !std::is_member_object_pointer_v<decltype(Data)>,
640 &internal::type_info<data_type>::resolve,
641 &internal::setter<std::is_const_v<data_type>, Type, Data>,
642 &internal::getter<Type, Data, Policy>,
648 node.
prop = properties<std::integral_constant<decltype(Data), Data>>(std::forward<Property>(property)...);
651 static_assert(std::is_pointer_v<std::decay_t<decltype(Data)>>);
652 using data_type = std::remove_pointer_t<std::decay_t<decltype(Data)>>;
654 static internal::data_node node{
655 &internal::type_info<Type>::template
data<Data>,
660 std::is_const_v<data_type>,
661 !std::is_member_object_pointer_v<decltype(Data)>,
662 &internal::type_info<data_type>::resolve,
663 &internal::setter<std::is_const_v<data_type>, Type, Data>,
664 &internal::getter<Type, Data, Policy>,
670 node.
prop = properties<std::integral_constant<decltype(Data), Data>>(std::forward<Property>(property)...);
674 curr->identifier = identifier;
676 assert(!duplicate(curr->identifier, curr->next));
677 assert((!internal::type_info<Type>::template
data<Data>));
678 internal::type_info<Type>::template data<Data> = curr;
706 template<
auto Setter,
auto Getter,
typename Policy =
as_is_t,
typename... Property>
707 factory data(
const std::size_t identifier, Property &&... property) noexcept {
708 using owner_type = std::tuple<std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>;
709 using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
710 static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>);
711 auto *
const type = internal::type_info<Type>::resolve();
713 static internal::data_node node{
721 &internal::type_info<underlying_type>::resolve,
722 &internal::setter<false, Type, Setter>,
723 &internal::getter<Type, Getter, Policy>,
729 node.identifier = identifier;
731 node.prop = properties<owner_type>(std::forward<Property>(property)...);
732 assert(!duplicate(node.identifier, node.next));
734 internal::type_info<Type>::template data<Setter, Getter> = &node;
755 template<
auto Candidate,
typename Policy =
as_is_t,
typename... Property>
756 factory func(
const std::size_t identifier, Property &&... property) noexcept {
757 using owner_type = std::integral_constant<decltype(Candidate), Candidate>;
758 using helper_type = internal::function_helper_t<decltype(Candidate)>;
759 auto *
const type = internal::type_info<Type>::resolve();
761 static internal::func_node node{
768 helper_type::is_const,
769 !std::is_member_function_pointer_v<decltype(Candidate)>,
770 &internal::type_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void,
typename helper_type::return_type>>
::resolve,
773 return internal::invoke<Type, Candidate, Policy>(handle,
any, std::make_index_sequence<helper_type::size>{});
780 node.identifier = identifier;
782 node.prop = properties<owner_type>(std::forward<Property>(property)...);
783 assert(!duplicate(node.identifier, node.next));
785 internal::type_info<Type>::template func<Candidate> = &node;
803 const auto registered = internal::type_info<Type>::type;
806 if(
auto *curr = internal::type_info<>::type; curr == internal::type_info<Type>::type) {
807 internal::type_info<>::type = internal::type_info<Type>::type->next;
809 while(curr && curr->next != internal::type_info<Type>::type) {
814 curr->next = internal::type_info<Type>::type->next;
818 unregister_prop(&internal::type_info<Type>::type->prop);
819 unregister_all<&internal::type_node::base>(0);
820 unregister_all<&internal::type_node::conv>(0);
821 unregister_all<&internal::type_node::ctor>(0);
822 unregister_all<&internal::type_node::data>(0);
823 unregister_all<&internal::type_node::func>(0);
826 internal::type_info<Type>::type->identifier = {};
827 internal::type_info<Type>::type->next =
nullptr;
828 internal::type_info<Type>::type =
nullptr;
850 template<
typename Type,
typename... Property>
867 template<
typename Type>
885 template<
typename Type>
896 template<
typename Type>
898 return internal::type_info<Type>::resolve()->clazz();
908 const auto *curr = internal::find_if([identifier](
auto *node) {
909 return node->identifier == identifier;
910 }, internal::type_info<>::type);
912 return curr ? curr->clazz() :
type{};
921 template<
typename Op>
922 inline std::enable_if_t<std::is_invocable_v<Op, type>,
void>
924 internal::iterate([op = std::move(op)](
auto *node) {
926 }, internal::type_info<>::type);
933 #endif // META_FACTORY_HPP