Skip to content

Commit e129da6

Browse files
author
kelbon
committed
anyany_method2 / anyany_method2_n
1 parent a1fd13e commit e129da6

File tree

1 file changed

+78
-28
lines changed

1 file changed

+78
-28
lines changed

include/anyany/anyany_macro.hpp

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ template <typename Ret, typename Self, typename... Args>
1414
struct get_return_type<Ret(Self, Args...)> {
1515
using type = Ret;
1616
};
17-
template<typename Signature>
17+
template <typename Signature>
1818
using 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

Comments
 (0)