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