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/type_erasure/detail/member11.hpp> 15 16 #ifndef BOOST_TYPE_ERASURE_MEMBER 17 18 #include <boost/detail/workaround.hpp> 19 #include <boost/preprocessor/cat.hpp> 20 #include <boost/preprocessor/dec.hpp> 21 #include <boost/preprocessor/comma_if.hpp> 22 #include <boost/preprocessor/repetition/enum.hpp> 23 #include <boost/preprocessor/repetition/enum_trailing.hpp> 24 #include <boost/preprocessor/repetition/enum_params.hpp> 25 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 26 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 27 #include <boost/preprocessor/seq/size.hpp> 28 #include <boost/preprocessor/seq/elem.hpp> 29 #include <boost/preprocessor/tuple/elem.hpp> 30 #include <boost/type_erasure/detail/macro.hpp> 31 #include <boost/type_erasure/detail/const.hpp> 32 #include <boost/type_erasure/rebind_any.hpp> 33 #include <boost/type_erasure/placeholder.hpp> 34 #include <boost/type_erasure/call.hpp> 35 #include <boost/type_erasure/concept_interface.hpp> 36 37 /** INTERNAL ONLY */ 38 #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \ 39 typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n) 40 41 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ 42 defined(BOOST_TYPE_ERASURE_DOXYGEN) || \ 43 BOOST_WORKAROUND(BOOST_MSVC, == 1800) 44 45 /** INTERNAL ONLY */ 46 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ 47 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T> 48 49 /** INTERNAL ONLY */ 50 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) 51 /** INTERNAL ONLY */ 52 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X) 53 54 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 55 56 /** INTERNAL ONLY */ 57 #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)) 58 /** INTERNAL ONLY */ 59 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x)) 60 /** INTERNAL ONLY*/ 61 #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)) 62 /** INTERNAL ONLY*/ 63 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~) 64 65 #else 66 67 /** INTERNAL ONLY */ 68 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x) 69 /** INTERNAL ONLY*/ 70 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a) 71 72 #endif 73 74 /** INTERNAL ONLY */ 75 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) 76 /** INTERNAL ONLY */ 77 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x) 78 /** INTERNAL ONLY */ 79 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~) 80 81 #ifdef BOOST_TYPE_ERASURE_DOXYGEN 82 83 /** 84 * \brief Defines a primitive concept for a member function. 85 * 86 * \param concept_name is the name of the concept to declare. 87 * If it is omitted it defaults to <code>has_ ## member</code> 88 * \param member is the name of the member function. 89 * 90 * The declaration of the concept is 91 * \code 92 * template<class Sig, class T = _self> 93 * struct concept_name; 94 * \endcode 95 * where @c Sig is a function type giving the 96 * signature of the member function, and @c T is the 97 * object type. @c T may be const-qualified for 98 * const member functions. @c concept_name<R(A...) const, T> 99 * is an alias for @c concept_name<R(A...), const T>. 100 * 101 * This macro can only be used at namespace scope. 102 * 103 * Example: 104 * 105 * \code 106 * namespace boost { 107 * BOOST_TYPE_ERASURE_MEMBER(push_back) 108 * } 109 * typedef boost::has_push_back<void(int)> push_back_concept; 110 * \endcode 111 * 112 * The concept defined by this function may be specialized to 113 * provide a concept_map. The class object will be passed by 114 * reference as the first parameter. 115 * 116 * \code 117 * template<> 118 * struct has_push_back<void(int), std::list<int> > { 119 * static void apply(std::list<int>& l, int i) { l.push_back(i); } 120 * }; 121 * \endcode 122 * 123 * In C++03, the macro can only be used in the global namespace and 124 * is defined as: 125 * 126 * \code 127 * #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) 128 * \endcode 129 * 130 * Example: 131 * 132 * \code 133 * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1) 134 * typedef boost::has_push_back<void(int), _self> push_back_concept; 135 * \endcode 136 * 137 * For backwards compatibility, this form is always accepted. 138 */ 139 #define BOOST_TYPE_ERASURE_MEMBER(concept_name, member) /**/ 140 141 #else 142 143 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \ 144 BOOST_TYPE_ERASURE_MEMBER_I( \ 145 qualified_name, \ 146 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ 147 member, \ 148 N) 149 150 #endif 151 152 #else 153 154 /** INTERNAL ONLY */ 155 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ 156 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T> 157 158 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A 159 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X... 160 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 161 # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)... 162 # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)... 163 #else 164 # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) x... 165 # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , a... 166 #endif 167 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... 168 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x 169 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a 170 171 172 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \ 173 BOOST_TYPE_ERASURE_MEMBER_I( \ 174 qualified_name, \ 175 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ 176 member, \ 177 N) 178 179 #endif 180 181 /** INTERNAL ONLY */ 182 #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \ 183 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ 184 template<class Sig, class T = ::boost::type_erasure::_self> \ 185 struct concept_name; \ 186 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \ 187 struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ 188 static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ 189 { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ 190 }; \ 191 template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \ 192 struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ 193 static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ 194 { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ 195 }; \ 196 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \ 197 namespace boost { \ 198 namespace type_erasure { \ 199 template< \ 200 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ 201 class T, class Base, class Enable> \ 202 struct concept_interface< \ 203 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ 204 Base, \ 205 typename ::boost::enable_if< \ 206 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \ 207 typename ::boost::remove_const<T>::type \ 208 >::type, \ 209 Enable \ 210 > : Base \ 211 { \ 212 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ 213 typename rebind_any<Base, R>::type member( \ 214 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ 215 { \ 216 return ::boost::type_erasure::call( \ 217 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ 218 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ 219 } \ 220 }; \ 221 template< \ 222 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ 223 class T, class Base, class Enable> \ 224 struct concept_interface< \ 225 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ 226 Base, \ 227 typename ::boost::enable_if< \ 228 ::boost::type_erasure::detail::should_be_const<T, Base>, \ 229 typename ::boost::remove_const<T>::type \ 230 >::type, \ 231 Enable \ 232 > : Base \ 233 { \ 234 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ 235 typename rebind_any<Base, R>::type member( \ 236 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ 237 { \ 238 return ::boost::type_erasure::call( \ 239 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ 240 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ 241 } \ 242 }; \ 243 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \ 244 struct concept_interface< \ 245 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ 246 Base, \ 247 typename ::boost::enable_if< \ 248 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \ 249 typename ::boost::remove_const<T>::type \ 250 >::type, \ 251 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ 252 { \ 253 using Base::member; \ 254 typename rebind_any<Base, R>::type member( \ 255 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ 256 { \ 257 return ::boost::type_erasure::call( \ 258 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ 259 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ 260 } \ 261 }; \ 262 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \ 263 struct concept_interface< \ 264 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ 265 Base, \ 266 typename ::boost::enable_if< \ 267 ::boost::type_erasure::detail::should_be_const<T, Base>, \ 268 typename ::boost::remove_const<T>::type \ 269 >::type, \ 270 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ 271 { \ 272 using Base::member; \ 273 typename rebind_any<Base, R>::type member( \ 274 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ 275 { \ 276 return ::boost::type_erasure::call( \ 277 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ 278 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ 279 } \ 280 }; \ 281 }} 282 283 /** INTERNAL ONLY */ 284 #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\ 285 BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N) 286 287 #endif 288 289 #endif 290