File indexing completed on 2025-12-16 10:10:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
0012 #define BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
0013
0014 #include <iosfwd>
0015 #include <boost/utility/enable_if.hpp>
0016 #include <boost/type_erasure/detail/const.hpp>
0017 #include <boost/type_erasure/call.hpp>
0018 #include <boost/type_erasure/concept_interface.hpp>
0019 #include <boost/type_erasure/placeholder.hpp>
0020 #include <boost/type_erasure/concept_of.hpp>
0021 #include <boost/type_erasure/derived.hpp>
0022 #include <boost/type_erasure/rebind_any.hpp>
0023 #include <boost/type_erasure/param.hpp>
0024 #include <boost/type_erasure/check_match.hpp>
0025 #include <boost/type_erasure/relaxed.hpp>
0026 #include <boost/type_erasure/typeid_of.hpp>
0027
0028 namespace boost {
0029 namespace type_erasure {
0030
0031
0032 #define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \
0033 template<class T = _self> \
0034 struct name \
0035 { \
0036 static void apply(T& arg) { op arg; } \
0037 }; \
0038 \
0039 template<class T, class Base> \
0040 struct concept_interface<name<T>, Base, T, \
0041 typename ::boost::enable_if< \
0042 detail::should_be_non_const<T, Base> \
0043 >::type \
0044 > : Base \
0045 { \
0046 typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
0047 _derived& operator op() \
0048 { \
0049 ::boost::type_erasure::call(name<T>(), *this); \
0050 return static_cast<_derived&>(*this); \
0051 } \
0052 typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) \
0053 { \
0054 typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
0055 static_cast<_derived&>(*this)); \
0056 ::boost::type_erasure::call(name<T>(), *this); \
0057 return result; \
0058 } \
0059 }; \
0060 \
0061 template<class T, class Base> \
0062 struct concept_interface<name<T>, Base, T, \
0063 typename ::boost::enable_if< \
0064 detail::should_be_const<T, Base> \
0065 >::type \
0066 > : Base \
0067 { \
0068 typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
0069 const _derived& operator op() const \
0070 { \
0071 ::boost::type_erasure::call(name<T>(), *this); \
0072 return static_cast<const _derived&>(*this); \
0073 } \
0074 typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) const \
0075 { \
0076 typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
0077 static_cast<const _derived&>(*this)); \
0078 ::boost::type_erasure::call(name<T>(), *this); \
0079 return result; \
0080 } \
0081 };
0082
0083
0084
0085
0086
0087
0088 BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(incrementable, ++)
0089
0090
0091
0092
0093
0094 BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(decrementable, --)
0095
0096 #undef BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR
0097
0098
0099 #define BOOST_TYPE_ERASURE_UNARY_OPERATOR(name, op) \
0100 template<class T = _self, class R = T> \
0101 struct name \
0102 { \
0103 static R apply(const T& arg) { return op arg; } \
0104 }; \
0105 \
0106 template<class T, class R, class Base> \
0107 struct concept_interface<name<T, R>, Base, T> : Base \
0108 { \
0109 typename ::boost::type_erasure::rebind_any<Base, R>::type operator op() const \
0110 { \
0111 return ::boost::type_erasure::call(name<T, R>(), *this); \
0112 } \
0113 };
0114
0115
0116
0117
0118
0119 BOOST_TYPE_ERASURE_UNARY_OPERATOR(complementable, ~)
0120
0121
0122
0123
0124 BOOST_TYPE_ERASURE_UNARY_OPERATOR(negatable, -)
0125
0126 #undef BOOST_TYPE_ERASURE_UNARY_OPERATOR
0127
0128 template<class R, class T = _self>
0129 struct dereferenceable
0130 {
0131 static R apply(const T& arg) { return *arg; }
0132 };
0133
0134
0135
0136 template<class R, class T, class Base>
0137 struct concept_interface<dereferenceable<R, T>, Base, T> : Base
0138 {
0139 typename ::boost::type_erasure::rebind_any<Base, R>::type operator*() const
0140 {
0141 return ::boost::type_erasure::call(dereferenceable<R, T>(), *this);
0142 }
0143 };
0144
0145
0146
0147
0148 #define BOOST_TYPE_ERASURE_BINARY_OPERATOR(name, op) \
0149 template<class T = _self, class U = T, class R = T> \
0150 struct name \
0151 { \
0152 static R apply(const T& lhs, const U& rhs) { return lhs op rhs; } \
0153 }; \
0154 \
0155 template<class T, class U, class R, class Base> \
0156 struct concept_interface<name<T, U, R>, Base, T> : Base \
0157 { \
0158 friend typename rebind_any<Base, R>::type \
0159 operator op(const typename derived<Base>::type& lhs, \
0160 typename as_param<Base, const U&>::type rhs) \
0161 { \
0162 return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
0163 } \
0164 }; \
0165 \
0166 template<class T, class U, class R, class Base> \
0167 struct concept_interface< \
0168 name<T, U, R>, \
0169 Base, \
0170 U, \
0171 typename ::boost::disable_if< \
0172 ::boost::type_erasure::is_placeholder<T> >::type \
0173 > : Base \
0174 { \
0175 friend typename rebind_any<Base, R>::type \
0176 operator op(const T& lhs, \
0177 const typename derived<Base>::type& rhs) \
0178 { \
0179 return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
0180 } \
0181 };
0182
0183 BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +)
0184 BOOST_TYPE_ERASURE_BINARY_OPERATOR(subtractable, -)
0185 BOOST_TYPE_ERASURE_BINARY_OPERATOR(multipliable, *)
0186 BOOST_TYPE_ERASURE_BINARY_OPERATOR(dividable, /)
0187 BOOST_TYPE_ERASURE_BINARY_OPERATOR(modable, %)
0188 BOOST_TYPE_ERASURE_BINARY_OPERATOR(left_shiftable, <<)
0189 BOOST_TYPE_ERASURE_BINARY_OPERATOR(right_shiftable, >>)
0190 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitandable, &)
0191 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitorable, |)
0192 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitxorable, ^)
0193
0194 #undef BOOST_TYPE_ERASURE_BINARY_OPERATOR
0195
0196
0197 #define BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(name, op) \
0198 template<class T = _self, class U = T> \
0199 struct name \
0200 { \
0201 static void apply(T& lhs, const U& rhs) { lhs op rhs; } \
0202 }; \
0203 \
0204 template<class T, class U, class Base> \
0205 struct concept_interface<name<T, U>, Base, T, \
0206 typename ::boost::disable_if< \
0207 ::boost::is_same< \
0208 typename ::boost::type_erasure::placeholder_of<Base>::type, \
0209 const T& \
0210 > \
0211 >::type \
0212 > : Base \
0213 { \
0214 friend typename detail::non_const_this_param<Base>::type& \
0215 operator op(typename detail::non_const_this_param<Base>::type& lhs, \
0216 typename as_param<Base, const U&>::type rhs) \
0217 { \
0218 ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
0219 return lhs; \
0220 } \
0221 }; \
0222 \
0223 template<class T, class U, class Base> \
0224 struct concept_interface< \
0225 name<T, U>, \
0226 Base, \
0227 U, \
0228 typename ::boost::disable_if< \
0229 ::boost::type_erasure::is_placeholder<T> >::type \
0230 > : Base \
0231 { \
0232 friend T& \
0233 operator op(T& lhs, const typename derived<Base>::type& rhs) \
0234 { \
0235 ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
0236 return lhs; \
0237 } \
0238 };
0239
0240 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(add_assignable, +=)
0241 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(subtract_assignable, -=)
0242 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(multiply_assignable, *=)
0243 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(divide_assignable, /=)
0244 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(mod_assignable, %=)
0245 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(left_shift_assignable, <<=)
0246 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(right_shift_assignable, >>=)
0247 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitand_assignable, &=)
0248 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitor_assignable, |=)
0249 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitxor_assignable, ^=)
0250
0251 #undef BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR
0252
0253 template<class T = _self, class U = T>
0254 struct equality_comparable
0255 {
0256 static bool apply(const T& lhs, const U& rhs) { return lhs == rhs; }
0257 };
0258
0259
0260
0261 template<class T, class U, class Base>
0262 struct concept_interface<equality_comparable<T, U>, Base, T> : Base
0263 {
0264 friend bool operator==(const typename derived<Base>::type& lhs,
0265 typename as_param<Base, const U&>::type rhs)
0266 {
0267 if(::boost::type_erasure::check_match(equality_comparable<T, U>(), lhs, rhs)) {
0268 return ::boost::type_erasure::unchecked_call(equality_comparable<T, U>(), lhs, rhs);
0269 } else {
0270 return false;
0271 }
0272 }
0273 friend bool operator!=(const typename derived<Base>::type& lhs,
0274 typename as_param<Base, const U&>::type rhs)
0275 {
0276 return !(lhs == rhs);
0277 }
0278 };
0279
0280 template<class T, class U, class Base>
0281 struct concept_interface<
0282 equality_comparable<T, U>,
0283 Base,
0284 U,
0285 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
0286 > : Base
0287 {
0288 friend bool operator==(const T& lhs, const typename derived<Base>::type& rhs)
0289 {
0290 return ::boost::type_erasure::call(equality_comparable<T, U>(), lhs, rhs);
0291 }
0292 friend bool operator!=(const T& lhs, const typename derived<Base>::type& rhs)
0293 {
0294 return !(lhs == rhs);
0295 }
0296 };
0297
0298
0299
0300 template<class T = _self, class U = T>
0301 struct less_than_comparable
0302 {
0303 static bool apply(const T& lhs, const U& rhs) { return lhs < rhs; }
0304 };
0305
0306 namespace detail {
0307
0308 template<class F, class T, class U>
0309 bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::true_)
0310 {
0311 if(::boost::type_erasure::check_match(f, lhs, rhs)) {
0312 return ::boost::type_erasure::unchecked_call(f, lhs, rhs);
0313 } else {
0314 return ::boost::type_erasure::typeid_of(
0315 static_cast<const typename derived<T>::type&>(lhs)
0316 ).before(
0317 ::boost::type_erasure::typeid_of(
0318 static_cast<const typename derived<U>::type&>(rhs)
0319 )
0320 ) != false;
0321 }
0322 }
0323
0324 template<class F, class T, class U>
0325 bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::false_)
0326 {
0327 return ::boost::type_erasure::call(f, lhs, rhs);
0328 }
0329
0330 }
0331
0332
0333
0334 template<class T, class Base>
0335 struct concept_interface<less_than_comparable<T, T>, Base, T> : Base
0336 {
0337 friend bool operator<(const typename derived<Base>::type& lhs,
0338 typename as_param<Base, const T&>::type rhs)
0339 {
0340 return ::boost::type_erasure::detail::less_impl(
0341 less_than_comparable<T, T>(),
0342 lhs, rhs,
0343 ::boost::type_erasure::is_relaxed<
0344 typename ::boost::type_erasure::concept_of<Base>::type>());
0345 }
0346 friend bool operator>=(const typename derived<Base>::type& lhs,
0347 typename as_param<Base, const T&>::type rhs)
0348 {
0349 return !(lhs < rhs);
0350 }
0351 friend bool operator>(typename as_param<Base, const T&>::type lhs,
0352 const typename derived<Base>::type& rhs)
0353 {
0354 return rhs < lhs;
0355 }
0356 friend bool operator<=(typename as_param<Base, const T&>::type lhs,
0357 const typename derived<Base>::type& rhs)
0358 {
0359 return !(rhs < lhs);
0360 }
0361 };
0362
0363 template<class T, class U, class Base>
0364 struct concept_interface<less_than_comparable<T, U>, Base, T> : Base
0365 {
0366 friend bool operator<(const typename derived<Base>::type& lhs,
0367 typename as_param<Base, const U&>::type rhs)
0368 {
0369 return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
0370 }
0371 friend bool operator>=(const typename derived<Base>::type& lhs,
0372 typename as_param<Base, const U&>::type rhs)
0373 {
0374 return !(lhs < rhs);
0375 }
0376 friend bool operator>(typename as_param<Base, const U&>::type lhs,
0377 const typename derived<Base>::type& rhs)
0378 {
0379 return rhs < lhs;
0380 }
0381 friend bool operator<=(typename as_param<Base, const U&>::type lhs,
0382 const typename derived<Base>::type& rhs)
0383 {
0384 return !(rhs < lhs);
0385 }
0386 };
0387
0388 template<class T, class U, class Base>
0389 struct concept_interface<
0390 less_than_comparable<T, U>,
0391 Base,
0392 U,
0393 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
0394 > : Base
0395 {
0396 friend bool operator<(const T& lhs, const typename derived<Base>::type& rhs)
0397 {
0398 return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
0399 }
0400 friend bool operator>=(const T& lhs, const typename derived<Base>::type& rhs)
0401 {
0402 return !(lhs < rhs);
0403 }
0404 friend bool operator>(const typename derived<Base>::type& lhs, const T& rhs)
0405 {
0406 return rhs < lhs;
0407 }
0408 friend bool operator<=(const typename derived<Base>::type& lhs, const T& rhs)
0409 {
0410 return !(rhs < lhs);
0411 }
0412 };
0413
0414
0415
0416 template<class R, class T = _self, class N = std::ptrdiff_t>
0417 struct subscriptable
0418 {
0419 static R apply(T& arg, const N& index) { return arg[index]; }
0420 };
0421
0422
0423
0424 template<class R, class T, class N, class Base>
0425 struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
0426 typename ::boost::enable_if<
0427 ::boost::type_erasure::detail::should_be_non_const<T, Base>
0428 >::type
0429 > : Base
0430 {
0431 typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
0432 typename ::boost::type_erasure::as_param<Base, const N&>::type index)
0433 {
0434 return ::boost::type_erasure::call(subscriptable<R, T, N>(), *this, index);
0435 }
0436 };
0437
0438 template<class R, class T, class N, class Base>
0439 struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
0440 typename ::boost::enable_if<
0441 ::boost::type_erasure::detail::should_be_const<T, Base>
0442 >::type
0443 > : Base
0444 {
0445 typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
0446 typename ::boost::type_erasure::as_param<Base, const N&>::type index) const
0447 {
0448 return ::boost::type_erasure::call(subscriptable<R, const T, N>(), *this, index);
0449 }
0450 };
0451
0452
0453
0454
0455
0456
0457
0458 template<class Os = std::ostream, class T = _self>
0459 struct ostreamable
0460 {
0461 static void apply(Os& out, const T& arg) { out << arg; }
0462 };
0463
0464
0465
0466 template<class Base, class Os, class T>
0467 struct concept_interface<ostreamable<Os, T>, Base, Os> : Base
0468 {
0469 friend typename detail::non_const_this_param<Base>::type&
0470 operator<<(typename detail::non_const_this_param<Base>::type& lhs,
0471 typename ::boost::type_erasure::as_param<Base, const T&>::type rhs)
0472 {
0473 ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
0474 return lhs;
0475 }
0476 };
0477
0478 template<class Base, class Os, class T>
0479 struct concept_interface<
0480 ostreamable<Os, T>,
0481 Base,
0482 T,
0483 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Os> >::type
0484 > : Base
0485 {
0486 friend Os&
0487 operator<<(Os& lhs,
0488 const typename ::boost::type_erasure::derived<Base>::type& rhs)
0489 {
0490 ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
0491 return lhs;
0492 }
0493 };
0494
0495
0496
0497
0498
0499
0500
0501 template<class Is = std::istream, class T = _self>
0502 struct istreamable
0503 {
0504 static void apply(Is& out, T& arg) { out >> arg; }
0505 };
0506
0507
0508
0509
0510 template<class Base, class Is, class T>
0511 struct concept_interface<istreamable<Is, T>, Base, Is> : Base
0512 {
0513 friend typename detail::non_const_this_param<Base>::type&
0514 operator>>(typename detail::non_const_this_param<Base>::type& lhs,
0515 typename ::boost::type_erasure::as_param<Base, T&>::type rhs)
0516 {
0517 ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
0518 return lhs;
0519 }
0520 };
0521
0522 template<class Base, class Is, class T>
0523 struct concept_interface<
0524 istreamable<Is, T>,
0525 Base,
0526 T,
0527 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Is> >::type
0528 > : Base
0529 {
0530 friend Is&
0531 operator>>(Is& lhs,
0532 typename ::boost::type_erasure::derived<Base>::type& rhs)
0533 {
0534 ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
0535 return lhs;
0536 }
0537 };
0538
0539
0540
0541 }
0542 }
0543
0544 #endif