@@ -14,10 +14,10 @@ template <typename Ret, typename Self, typename... Args>
1414struct get_return_type <Ret(Self, Args...)> {
1515 using type = Ret;
1616};
17- template <typename Signature>
17+ template <typename Signature>
1818using return_type_of = typename get_return_type<Signature>::type;
1919
20- } // namespace noexport
20+ } // namespace aa:: noexport
2121
2222#define AA_IMPL_REMOVE_PARENS (...) __VA_ARGS__
2323#define AA_IMPL_TOK_first (a, ...) a
@@ -39,10 +39,16 @@ using return_type_of = typename get_return_type<Signature>::type;
3939#define AA_INJECT_SELF_IN_PARENS (...) (Self __VA_ARGS__)
4040#define AA_INJECT_INTERFACE_T_IN_PARENS (...) (int __VA_ARGS__)
4141
42- // usage: anyany_method(<METHOD_NAME>, (<SELF_ARGUMENT>, <METHOD_ARGS...>) requires(<EXPR>) -> <RETURN_TYPE>);
43- // where
44- // * <METHOD_NAME> - is a name, which will be used later in invoke<NAME> or any_with<NAME...>
45- // * <SELF_ARGUMENT> - is a '&' 'const &' or just nothing('') followed by self-argument name
42+ // usage: anyany_method_n(<STRUCT_NAME>, <METHOD_NAME>,
43+ // (<SELF_ARGUMENT>, <METHOD_ARGS...>) requires(<EXPR>) -> <RETURN_TYPE>);
44+ // where
45+ // * <STRUCT_NAME> - name of describing struct, for using in aa::any_with<STRUCT_NAME>, aa::invoke etc later
46+ // * <METHOD_NAME> - name for invoking after creating any_with. e.g. any_with<STRUCT_NAME> a;
47+ // a.METHOD_NAME(args...)
48+ //
49+ // * <SELF_ARGUMENT> - is a '&' 'const &' or just nothing('') followed by self-argument name, e.g. "& me" /
50+ // "const & self" or just "self" (means pass *this by copy)
51+ //
4652// * <METHOD_ARGS...> - set of Method parameters
4753// * <EXPR> - what will Method do
4854// * <RETURN_TYPE> - return type of Method. Must be non-dependent type
@@ -54,7 +60,6 @@ using return_type_of = typename get_return_type<Signature>::type;
5460// * this macro supports 'template' on top of it, so you can easy create template Methods
5561// * any_with/ref which uses Methods created by this macro are sfinae-friendly constructible
5662// this means, constrctors do not exist in overload resolution if <EXPR> is invlaid for this type
57- //
5863// anyany_method(foo, (& self, int i) requires(self.foo(x)) -> int)
5964// // type 'int' do not have method .foo which accepts 'int' and return type is convertible to 'int'
6065// static_assert(!is_constructible_v<any_with<foo>, int>);
@@ -63,37 +68,22 @@ using return_type_of = typename get_return_type<Signature>::type;
6368// like
6469// anyany_method(bar, (*something*) requires(std::enable_if_t<CONDITION>(), self + 5)->R);
6570//
66- // EXAMPLES:
67- // * just simple Method, accepts 'self' by const&, returns self.foo(x, y)
68- //
69- // anyany_method(foo, (const& self, int x, char y) requires(self.foo(x, y)) -> std::string);
70- //
71- // * template Method, accepts self by non-const reference, invokes 'visitor_' with 'value'
72- // returns void, so any return value from 'visitor_(value)' will be ignored even if it is not 'void'
73- //
74- // template <typename T>
75- // anyany_method(visit, (&visitor_, const T& value) requires(visitor_(value)) -> void);
76- //
77- // using any_visitor = aa::any_with<visit<int>, visit<double>>;
78- // any_visitor value = [](auto x) { std::cout << x; };
79- // value = [](auto x) { foo(x); };
80- //
81- #define anyany_method (NAME, ...) \
82- struct NAME { \
71+ #define anyany_method_n (STRUCT_NAME, METHOD_NAME, ...) \
72+ struct STRUCT_NAME { \
8373 private: \
84- using method_t = NAME; \
74+ using method_t = STRUCT_NAME; \
8575 template <typename , typename , typename > \
8676 struct make_plugin {}; \
8777 template <typename CRTP, typename Ret, typename ... Args, typename Method> \
8878 struct make_plugin <CRTP, Ret(int &, Args...), Method> { \
89- Ret NAME (Args... args) { \
79+ Ret METHOD_NAME (Args... args) { \
9080 return ::aa::noexport::invoke_fn<Method, ::aa::type_list<Args...>>{}(*static_cast <CRTP*>(this ), \
9181 static_cast <Args&&>(args)...); \
9282 } \
9383 }; \
9484 template <typename CRTP, typename Ret, typename ... Args, typename Method> \
9585 struct make_plugin <CRTP, Ret(const int &, Args...), Method> { \
96- Ret NAME (Args... args) const { \
86+ Ret METHOD_NAME (Args... args) const { \
9787 return ::aa::noexport::invoke_fn<Method, ::aa::type_list<Args...>>{}( \
9888 *static_cast <const CRTP*>(this ), static_cast <Args&&>(args)...); \
9989 } \
@@ -115,6 +105,25 @@ using return_type_of = typename get_return_type<Signature>::type;
115105 } \
116106 }
117107
108+ // usage: anyany_method(<NAME>, (<SELF_ARGUMENT>, <METHOD_ARGS...>) requires(<EXPR>) -> <RETURN_TYPE>);
109+ // see `anyany_method_n` for details
110+ // EXAMPLES:
111+ // * just simple Method, accepts 'self' by const&, returns self.foo(x, y)
112+ //
113+ // anyany_method(foo, (const& self, int x, char y) requires(self.foo(x, y)) -> std::string);
114+ //
115+ // * template Method, accepts self by non-const reference, invokes 'visitor_' with 'value'
116+ // returns void, so any return value from 'visitor_(value)' will be ignored even if it is not 'void'
117+ //
118+ // template <typename T>
119+ // anyany_method(visit, (&visitor_, const T& value) requires(visitor_(value)) -> void);
120+ //
121+ // using any_visitor = aa::any_with<visit<int>>;
122+ // any_visitor value = [](auto x) { std::cout << x; };
123+ // value = [](auto x) { foo(x); };
124+ //
125+ #define anyany_method (NAME, ...) anyany_method_n(NAME, NAME, __VA_ARGS__)
126+
118127// same as anyany_method, but do not generates plugin(you still can add it by specializing aa::plugin)
119128#define anyany_extern_method (NAME, ...) \
120129 struct NAME { \
@@ -149,4 +158,45 @@ using return_type_of = typename get_return_type<Signature>::type;
149158// do not declares plugin(you can still add it by creating specialization aa::plugin<Any, NAME>)
150159// example:
151160// anyany_pseudomethod(type_info, requires(aa::descriptor_v<T>) -> aa::descriptor_t)
152- #define anyany_pseudomethod (NAME, ...) AA_IMPL_ANYANY_PSEUDOMETHOD(NAME, () __VA_ARGS__)
161+ #define anyany_pseudomethod (NAME, ...) AA_IMPL_ANYANY_PSEUDOMETHOD(NAME, () __VA_ARGS__)
162+
163+ // same as `anyany_method`, but without SFINAE. This is usable for better compilation errors
164+ // may be easily replaced by anyany_method_n when sfinae will be required
165+ #define anyany_method2_n (STRUCT_NAME, METHOD_NAME, ...) \
166+ struct STRUCT_NAME { \
167+ private: \
168+ using method_t = STRUCT_NAME; \
169+ template <typename , typename , typename > \
170+ struct make_plugin {}; \
171+ template <typename CRTP, typename Ret, typename ... Args, typename Method> \
172+ struct make_plugin <CRTP, Ret(int &, Args...), Method> { \
173+ Ret METHOD_NAME (Args... args) { \
174+ return ::aa::noexport::invoke_fn<Method, ::aa::type_list<Args...>>{}(*static_cast <CRTP*>(this ), \
175+ static_cast <Args&&>(args)...); \
176+ } \
177+ }; \
178+ template <typename CRTP, typename Ret, typename ... Args, typename Method> \
179+ struct make_plugin <CRTP, Ret(const int &, Args...), Method> { \
180+ Ret METHOD_NAME (Args... args) const { \
181+ return ::aa::noexport::invoke_fn<Method, ::aa::type_list<Args...>>{}( \
182+ *static_cast <const CRTP*>(this ), static_cast <Args&&>(args)...); \
183+ } \
184+ }; \
185+ template <typename CRTP, typename Ret, typename ... Args, typename Method> \
186+ struct make_plugin <CRTP, Ret(int , Args...), Method> \
187+ : make_plugin<CRTP, Ret(const int &, Args...), Method> {}; \
188+ \
189+ public: \
190+ using signature_type = auto AA_EXPAND (AA_INJECT_INTERFACE_T_IN_PARENS AA_GET_TOKEN (first, __VA_ARGS__)) \
191+ AA_GET_ALL_AFTER_REQUIREMENT(__VA_ARGS__); \
192+ template <typename CRTP> \
193+ using plugin = make_plugin<CRTP, signature_type, method_t >; \
194+ using return_type = ::aa::noexport::return_type_of<signature_type>; \
195+ template <typename Self> \
196+ static auto do_invoke AA_EXPAND (AA_INJECT_SELF_IN_PARENS AA_GET_TOKEN (first, __VA_ARGS__)) \
197+ -> return_type { \
198+ return static_cast <return_type>(AA_GET_REQUIREMENT (__VA_ARGS__)); \
199+ } \
200+ }
201+
202+ #define anyany_method2 (NAME, ...) anyany_method2_n(NAME, NAME, __VA_ARGS__)
0 commit comments