]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.TypeErasure library |
2 | // | |
3 | // Copyright 2012-2013 Steven Watanabe | |
4 | // | |
5 | // Distributed under the Boost Software License Version 1.0. (See | |
6 | // accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // $Id$ | |
10 | ||
11 | #ifndef BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED | |
12 | #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED | |
13 | ||
14 | #include <boost/detail/workaround.hpp> | |
15 | #include <boost/preprocessor/cat.hpp> | |
16 | #include <boost/preprocessor/dec.hpp> | |
17 | #include <boost/preprocessor/comma_if.hpp> | |
18 | #include <boost/preprocessor/repetition/enum.hpp> | |
19 | #include <boost/preprocessor/repetition/enum_trailing.hpp> | |
20 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
21 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
22 | #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> | |
23 | #include <boost/preprocessor/seq/size.hpp> | |
24 | #include <boost/preprocessor/seq/elem.hpp> | |
25 | #include <boost/preprocessor/tuple/elem.hpp> | |
26 | #include <boost/type_erasure/detail/macro.hpp> | |
27 | #include <boost/type_erasure/detail/const.hpp> | |
28 | #include <boost/type_erasure/rebind_any.hpp> | |
29 | #include <boost/type_erasure/placeholder.hpp> | |
30 | #include <boost/type_erasure/call.hpp> | |
31 | #include <boost/type_erasure/concept_interface.hpp> | |
32 | ||
33 | /** INTERNAL ONLY */ | |
34 | #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \ | |
35 | typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n) | |
36 | ||
37 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ | |
38 | defined(BOOST_TYPE_ERASURE_DOXYGEN) || \ | |
39 | BOOST_WORKAROUND(BOOST_MSVC, == 1800) | |
40 | ||
41 | /** INTERNAL ONLY */ | |
42 | #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ | |
43 | BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T> | |
44 | ||
45 | /** INTERNAL ONLY */ | |
46 | #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) | |
47 | /** INTERNAL ONLY */ | |
48 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X) | |
49 | ||
50 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
51 | ||
52 | /** INTERNAL ONLY */ | |
53 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD(z, n, data) ::std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n)>(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n)) | |
54 | /** INTERNAL ONLY */ | |
55 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x)) | |
56 | /** INTERNAL ONLY*/ | |
57 | #define BOOST_TYPE_ERASURE_FORWARD_REBIND1(z, n, data) ::std::forward<typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type>(BOOST_PP_CAT(a, n)) | |
58 | /** INTERNAL ONLY*/ | |
59 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~) | |
60 | ||
61 | #else | |
62 | ||
63 | /** INTERNAL ONLY */ | |
64 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x) | |
65 | /** INTERNAL ONLY*/ | |
66 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a) | |
67 | ||
68 | #endif | |
69 | ||
70 | /** INTERNAL ONLY */ | |
71 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) | |
72 | /** INTERNAL ONLY */ | |
73 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x) | |
74 | /** INTERNAL ONLY */ | |
75 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~) | |
76 | ||
77 | /** | |
78 | * \brief Defines a primitive concept for a member function. | |
79 | * | |
80 | * \param qualified_name should be a preprocessor sequence | |
81 | * of the form (namespace1)(namespace2)...(concept_name). | |
82 | * \param member is the name of the member function. | |
83 | * \param N is the number of arguments of the function. | |
84 | * | |
85 | * The declaration of the concept is | |
86 | * \code | |
87 | * template<class Sig, class T = _self> | |
88 | * struct ::namespace1::namespace2::...::concept_name; | |
89 | * \endcode | |
90 | * where Sig is a function type giving the | |
91 | * signature of the member function, and T is the | |
92 | * object type. T may be const-qualified for | |
93 | * const member functions. | |
94 | * | |
95 | * This macro can only be used in the global namespace. | |
96 | * | |
97 | * Example: | |
98 | * | |
99 | * \code | |
100 | * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1) | |
101 | * typedef boost::has_push_back<void(int), _self> push_back_concept; | |
102 | * \endcode | |
103 | * | |
104 | * \note In C++11 the argument N is ignored and may be omitted. | |
105 | * BOOST_TYPE_ERASURE_MEMBER will always define a variadic concept. | |
106 | */ | |
107 | #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \ | |
108 | BOOST_TYPE_ERASURE_MEMBER_I( \ | |
109 | qualified_name, \ | |
110 | BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ | |
111 | member, \ | |
112 | N) | |
113 | ||
114 | #else | |
115 | ||
116 | /** INTERNAL ONLY */ | |
117 | #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ | |
118 | BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T> | |
119 | ||
120 | #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A | |
121 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X... | |
122 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)... | |
123 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... | |
124 | #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)... | |
125 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x | |
126 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a | |
127 | ||
128 | ||
129 | #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \ | |
130 | BOOST_TYPE_ERASURE_MEMBER_I( \ | |
131 | qualified_name, \ | |
132 | BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ | |
133 | member, \ | |
134 | N) | |
135 | ||
136 | #endif | |
137 | ||
138 | /** INTERNAL ONLY */ | |
139 | #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \ | |
140 | BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ | |
141 | template<class Sig, class T = ::boost::type_erasure::_self> \ | |
142 | struct concept_name; \ | |
143 | template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \ | |
144 | struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ | |
145 | static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ | |
146 | { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ | |
147 | }; \ | |
148 | template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \ | |
149 | struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ | |
150 | static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ | |
151 | { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ | |
152 | }; \ | |
153 | BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \ | |
154 | namespace boost { \ | |
155 | namespace type_erasure { \ | |
156 | template< \ | |
157 | class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ | |
158 | class T, class Base, class Enable> \ | |
159 | struct concept_interface< \ | |
160 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ | |
161 | Base, \ | |
162 | typename ::boost::enable_if< \ | |
163 | ::boost::type_erasure::detail::should_be_non_const<T, Base>, \ | |
164 | typename ::boost::remove_const<T>::type \ | |
165 | >::type, \ | |
166 | Enable \ | |
167 | > : Base \ | |
168 | { \ | |
169 | typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ | |
170 | typename rebind_any<Base, R>::type member( \ | |
171 | BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ | |
172 | { \ | |
173 | return ::boost::type_erasure::call( \ | |
174 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ | |
175 | *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ | |
176 | } \ | |
177 | }; \ | |
178 | template< \ | |
179 | class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ | |
180 | class T, class Base, class Enable> \ | |
181 | struct concept_interface< \ | |
182 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ | |
183 | Base, \ | |
184 | typename ::boost::enable_if< \ | |
185 | ::boost::type_erasure::detail::should_be_const<T, Base>, \ | |
186 | typename ::boost::remove_const<T>::type \ | |
187 | >::type, \ | |
188 | Enable \ | |
189 | > : Base \ | |
190 | { \ | |
191 | typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ | |
192 | typename rebind_any<Base, R>::type member( \ | |
193 | BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ | |
194 | { \ | |
195 | return ::boost::type_erasure::call( \ | |
196 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ | |
197 | *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ | |
198 | } \ | |
199 | }; \ | |
200 | template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \ | |
201 | struct concept_interface< \ | |
202 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ | |
203 | Base, \ | |
204 | typename ::boost::enable_if< \ | |
205 | ::boost::type_erasure::detail::should_be_non_const<T, Base>, \ | |
206 | typename ::boost::remove_const<T>::type \ | |
207 | >::type, \ | |
208 | typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ | |
209 | { \ | |
210 | using Base::member; \ | |
211 | typename rebind_any<Base, R>::type member( \ | |
212 | BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ | |
213 | { \ | |
214 | return ::boost::type_erasure::call( \ | |
215 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ | |
216 | *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ | |
217 | } \ | |
218 | }; \ | |
219 | template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \ | |
220 | struct concept_interface< \ | |
221 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ | |
222 | Base, \ | |
223 | typename ::boost::enable_if< \ | |
224 | ::boost::type_erasure::detail::should_be_const<T, Base>, \ | |
225 | typename ::boost::remove_const<T>::type \ | |
226 | >::type, \ | |
227 | typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ | |
228 | { \ | |
229 | using Base::member; \ | |
230 | typename rebind_any<Base, R>::type member( \ | |
231 | BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ | |
232 | { \ | |
233 | return ::boost::type_erasure::call( \ | |
234 | BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ | |
235 | *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ | |
236 | } \ | |
237 | }; \ | |
238 | }} | |
239 | ||
240 | /** INTERNAL ONLY */ | |
241 | #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\ | |
242 | BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N) | |
243 | ||
244 | #endif |