Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:51

0001 /*=============================================================================
0002     Copyright (c) 2014 Paul Fultz II
0003     placeholders.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
0009 #define BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
0010 
0011 /// placeholders
0012 /// ============
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The placeholders provide `std::bind` compatible placeholders that
0018 /// additionally provide basic C++ operators that creates bind expressions.
0019 /// Each bind expression supports `constexpr` function evaluation.
0020 /// 
0021 /// Synopsis
0022 /// --------
0023 /// 
0024 ///     namespace placeholders {
0025 ///         placeholder<1> _1 = {};
0026 ///         placeholder<2> _2 = {};
0027 ///         placeholder<3> _3 = {};
0028 ///         placeholder<4> _4 = {};
0029 ///         placeholder<5> _5 = {};
0030 ///         placeholder<6> _6 = {};
0031 ///         placeholder<7> _7 = {};
0032 ///         placeholder<8> _8 = {};
0033 ///         placeholder<9> _9 = {};
0034 ///     }
0035 /// 
0036 /// Operators
0037 /// ---------
0038 /// 
0039 /// * Binary operators: +,-,*,/,%,>>,<<,>,<,<=,>=,==,!=,&,^,|,&&,||
0040 /// * Assign operators: +=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=
0041 /// * Unary operators: !,~,+,-,*,++,--
0042 /// 
0043 /// 
0044 /// Example
0045 /// -------
0046 /// 
0047 ///     #include <boost/hof.hpp>
0048 ///     #include <cassert>
0049 ///     using namespace boost::hof;
0050 /// 
0051 ///     int main() {
0052 ///         auto sum = _1 + _2;
0053 ///         assert(3 == sum(1, 2));
0054 ///     }
0055 /// 
0056 /// 
0057 /// unamed placeholder
0058 /// ==================
0059 /// 
0060 /// Description
0061 /// -----------
0062 /// 
0063 /// The unamed placeholder can be used to build simple functions from C++
0064 /// operators. 
0065 /// 
0066 /// Note: The function produced by the unamed placeholder is not a bind expression.
0067 /// 
0068 /// Synopsis
0069 /// --------
0070 /// 
0071 ///     namespace placeholders {
0072 ///         /* unspecified */ _ = {};
0073 ///     }
0074 /// 
0075 /// Example
0076 /// -------
0077 /// 
0078 ///     #include <boost/hof.hpp>
0079 ///     #include <cassert>
0080 ///     using namespace boost::hof;
0081 /// 
0082 ///     int main() {
0083 ///         auto sum = _ + _;
0084 ///         assert(3 == sum(1, 2));
0085 ///     }
0086 /// 
0087 
0088 #include <boost/hof/returns.hpp>
0089 #include <boost/hof/lazy.hpp>
0090 #include <boost/hof/protect.hpp>
0091 
0092 #if defined(_MSC_VER) && _MSC_VER >= 1910
0093 #include <boost/hof/detail/pp.hpp>
0094 #endif
0095 
0096 namespace boost { namespace hof { namespace detail {
0097     template<int N>
0098     struct simple_placeholder
0099     {};
0100 }}} // namespace boost::hof
0101 
0102 namespace std {
0103     template<int N>
0104     struct is_placeholder<boost::hof::detail::simple_placeholder<N>>
0105     : std::integral_constant<int, N>
0106     {};
0107 }
0108 
0109 
0110 namespace boost { namespace hof {
0111 
0112 #define BOOST_HOF_FOREACH_BINARY_OP(m) \
0113     m(+, add) \
0114     m(-, subtract) \
0115     m(*, multiply) \
0116     m(/, divide) \
0117     m(%, remainder) \
0118     m(>>, shift_right) \
0119     m(<<, shift_left) \
0120     m(>, greater_than) \
0121     m(<, less_than) \
0122     m(<=, less_than_equal) \
0123     m(>=, greater_than_equal) \
0124     m(==, equal) \
0125     m(!=, not_equal) \
0126     m(&, bit_and) \
0127     m(^, xor_) \
0128     m(|, bit_or) \
0129     m(&&, and_) \
0130     m(||, or_)
0131 
0132 #define BOOST_HOF_FOREACH_ASSIGN_OP(m) \
0133     m(+=, assign_add) \
0134     m(-=, assign_subtract) \
0135     m(*=, assign_multiply) \
0136     m(/=, assign_divide) \
0137     m(%=, assign_remainder) \
0138     m(>>=, assign_right_shift) \
0139     m(<<=, assign_left_shift) \
0140     m(&=, assign_bit_and) \
0141     m(|=, assign_bit_or) \
0142     m(^=, assign_xor)
0143 
0144 #ifndef _MSC_VER
0145 #define BOOST_HOF_FOREACH_UNARY_OP(m) \
0146     m(!, not_) \
0147     m(~, compl_) \
0148     m(+, unary_plus) \
0149     m(-, unary_subtract) \
0150     m(*, dereference) \
0151     m(++, increment) \
0152     m(--, decrement)
0153 #else
0154 #define BOOST_HOF_FOREACH_UNARY_OP(m) \
0155     m(!, not_) \
0156     m(~, compl_) \
0157     m(+, unary_plus) \
0158     m(-, unary_subtract) \
0159     m(*, dereference)
0160 #endif
0161 
0162 namespace operators {
0163 
0164 struct call
0165 {
0166     template<class F, class... Ts>
0167     constexpr auto operator()(F&& f, Ts&&... xs) const BOOST_HOF_RETURNS
0168     (f(BOOST_HOF_FORWARD(Ts)(xs)...));
0169 };
0170 
0171 // MSVC 2017 ICEs on && and || in conxtexpr, so we fallback on bitwise operators
0172 #if defined(_MSC_VER) && _MSC_VER >= 1910
0173 #define BOOST_HOF_BINARY_OP_SKIP_and_ ()
0174 #define BOOST_HOF_BINARY_OP_SKIP_or_ ()
0175 
0176 struct and_
0177 {
0178     template<class T, class U>
0179     constexpr auto operator()(T&& x, U&& y) const 
0180     noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y)))
0181     -> decltype(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y)) 
0182     { return BOOST_HOF_FORWARD(T)(x) & BOOST_HOF_FORWARD(U)(y); }
0183 };
0184 
0185 struct or_
0186 {
0187     template<class T, class U>
0188     constexpr auto operator()(T&& x, U&& y) const 
0189     noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y)))
0190     -> decltype(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y)) 
0191     { return BOOST_HOF_FORWARD(T)(x) | BOOST_HOF_FORWARD(U)(y); }
0192 };
0193 
0194 #define BOOST_HOF_BINARY_OP_IMPL(op, name) \
0195     struct name \
0196     { \
0197         template<class T, class U> \
0198         BOOST_HOF_USING(ex_failure, decltype(std::declval<T>() op std::declval<U>())); \
0199         struct failure : as_failure<ex_failure> {}; \
0200         template<class T, class U> \
0201         constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
0202         (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
0203     };
0204 
0205 #define BOOST_HOF_BINARY_OP(op, name) \
0206     BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_CAT(BOOST_HOF_BINARY_OP_SKIP_, name))) \
0207     (BOOST_HOF_PP_EMPTY, BOOST_HOF_BINARY_OP_IMPL)(op, name)
0208 
0209 #else
0210 
0211 #define BOOST_HOF_BINARY_OP(op, name) \
0212     struct name \
0213     { \
0214         template<class T, class U> \
0215         constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
0216         (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
0217     };
0218 
0219 #endif
0220 
0221 BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_BINARY_OP)
0222 BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_BINARY_OP)
0223 
0224 #define BOOST_HOF_UNARY_OP(op, name) \
0225     struct name \
0226     { \
0227         template<class T> \
0228         constexpr auto operator()(T&& x) const BOOST_HOF_RETURNS \
0229         (op(BOOST_HOF_FORWARD(T)(x))); \
0230     };
0231 
0232 
0233 BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNARY_OP)
0234 
0235 
0236 }
0237 
0238 template<int N>
0239 struct placeholder
0240 {
0241 #if BOOST_HOF_HAS_MANGLE_OVERLOAD
0242     template<class... Ts>
0243     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS 
0244     ( boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...) );
0245 #else
0246     template<class... Ts>
0247     struct result_call
0248     { typedef decltype(boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), std::declval<Ts>()...)) type; };
0249     template<class... Ts>
0250     constexpr typename result_call<Ts...>::type operator()(Ts&&... xs) const 
0251     { return boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...); };
0252 
0253 #endif
0254 
0255 #define BOOST_HOF_PLACEHOLDER_UNARY_OP(op, name) \
0256     constexpr auto operator op () const BOOST_HOF_RETURNS \
0257     ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>()) );
0258 
0259 BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_PLACEHOLDER_UNARY_OP)
0260 
0261 #define BOOST_HOF_PLACEHOLDER_ASSIGN_OP(op, name) \
0262     template<class T> \
0263     constexpr auto operator op (T&& x) const BOOST_HOF_RETURNS \
0264     ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) );
0265 
0266 BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_PLACEHOLDER_ASSIGN_OP)
0267 
0268 };
0269 
0270 #if BOOST_HOF_HAS_MANGLE_OVERLOAD
0271 
0272 #define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
0273     template<class T, int N> \
0274     constexpr inline auto operator op (const placeholder<N>&, T&& x) BOOST_HOF_RETURNS \
0275     ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) ); \
0276     template<class T, int N> \
0277     constexpr inline auto operator op (T&& x, const placeholder<N>&) BOOST_HOF_RETURNS \
0278     ( boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()) ); \
0279     template<int N, int M> \
0280     constexpr inline auto operator op (const placeholder<N>&, const placeholder<M>&) BOOST_HOF_RETURNS \
0281     ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()) );
0282 
0283 #else
0284 
0285 #define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
0286     template<class T, class U> \
0287     struct result_ ## name \
0288     { typedef decltype(boost::hof::lazy(operators::name())(std::declval<T>(), std::declval<U>())) type; }; \
0289     template<class T, int N> \
0290     constexpr inline typename result_ ## name<detail::simple_placeholder<N>, T>::type operator op (const placeholder<N>&, T&& x) \
0291     { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)); } \
0292     template<class T, int N> \
0293     constexpr inline typename result_ ## name<T, detail::simple_placeholder<N>>::type operator op (T&& x, const placeholder<N>&) \
0294     { return boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()); } \
0295     template<int N, int M> \
0296     constexpr inline typename result_ ## name<detail::simple_placeholder<N>, detail::simple_placeholder<M>>::type operator op (const placeholder<N>&, const placeholder<M>&) \
0297     { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()); }
0298 
0299 #endif
0300 
0301 BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_PLACEHOLDER_BINARY_OP)
0302 
0303 namespace placeholders {
0304 BOOST_HOF_DECLARE_STATIC_VAR(_1, placeholder<1>);
0305 BOOST_HOF_DECLARE_STATIC_VAR(_2, placeholder<2>);
0306 BOOST_HOF_DECLARE_STATIC_VAR(_3, placeholder<3>);
0307 BOOST_HOF_DECLARE_STATIC_VAR(_4, placeholder<4>);
0308 BOOST_HOF_DECLARE_STATIC_VAR(_5, placeholder<5>);
0309 BOOST_HOF_DECLARE_STATIC_VAR(_6, placeholder<6>);
0310 BOOST_HOF_DECLARE_STATIC_VAR(_7, placeholder<7>);
0311 BOOST_HOF_DECLARE_STATIC_VAR(_8, placeholder<8>);
0312 BOOST_HOF_DECLARE_STATIC_VAR(_9, placeholder<9>);
0313 }
0314 
0315 using placeholders::_1;
0316 using placeholders::_2;
0317 using placeholders::_3;
0318 using placeholders::_4;
0319 using placeholders::_5;
0320 using placeholders::_6;
0321 using placeholders::_7;
0322 using placeholders::_8;
0323 using placeholders::_9;
0324 
0325 namespace detail {
0326 
0327 
0328 
0329 struct unamed_placeholder
0330 {
0331 template<class T, class Invoker>
0332 struct partial_ap
0333 {
0334     T val;
0335 
0336     BOOST_HOF_INHERIT_DEFAULT_EMPTY(partial_ap, T)
0337 
0338     template<class X, class... Xs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, X&&, Xs&&...)>
0339     constexpr partial_ap(X&& x, Xs&&... xs) : val(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Xs)(xs)...)
0340     {}
0341 
0342     BOOST_HOF_RETURNS_CLASS(partial_ap);
0343 
0344     struct partial_ap_failure
0345     {
0346         template<class Failure>
0347         struct apply
0348         {
0349             template<class... Xs>
0350             struct of;
0351 
0352             template<class X>
0353             struct of<X>
0354             : Failure::template of<typename std::add_const<T>::type, X>
0355             {};
0356         };
0357     };
0358 
0359     struct failure
0360     : failure_map<partial_ap_failure, Invoker>
0361     {};
0362 
0363     template<class X>
0364     constexpr BOOST_HOF_SFINAE_RESULT(const Invoker&, id_<T>, id_<X>) 
0365     operator()(X&& x) const BOOST_HOF_SFINAE_RETURNS
0366     (
0367         Invoker()(BOOST_HOF_CONST_THIS->val, BOOST_HOF_FORWARD(X)(x))
0368     );
0369 };
0370 
0371 template<class Invoker, class T>
0372 static constexpr partial_ap<T, Invoker> make_partial_ap(T&& x)
0373 {
0374     return {BOOST_HOF_FORWARD(T)(x)};
0375 }
0376 
0377 template<class Op>
0378 struct left
0379 {
0380     struct failure
0381     : failure_for<Op>
0382     {};
0383     template<class T, class X>
0384     constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<T>, id_<X>) 
0385     operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
0386     (Op()(BOOST_HOF_FORWARD(T)(val), BOOST_HOF_FORWARD(X)(x)));
0387 };
0388 
0389 template<class Op>
0390 struct right
0391 {
0392     struct right_failure
0393     {
0394         template<class Failure>
0395         struct apply
0396         {
0397             template<class T, class U, class... Ts>
0398             struct of
0399             : Failure::template of<U, T, Ts...>
0400             {};
0401         };
0402     };
0403 
0404     struct failure
0405     : failure_map<right_failure, Op>
0406     {};
0407 
0408     template<class T, class X>
0409     constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<X>, id_<T>) 
0410     operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
0411     (Op()(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(T)(val)));
0412 };
0413 
0414 #define BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP(op, name) \
0415     constexpr auto operator op () const BOOST_HOF_RETURNS \
0416     ( operators::name() );
0417 
0418 BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP)
0419 
0420 #define BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP(op, name) \
0421     template<class T> \
0422     constexpr auto operator op (const T& x) const BOOST_HOF_RETURNS \
0423     ( partial_ap<T, left<operators::name>>(x) );
0424 
0425 BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP)
0426 };
0427 #define BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP(op, name) \
0428     template<class T> \
0429     constexpr inline auto operator op (const unamed_placeholder&, const T& x) BOOST_HOF_RETURNS \
0430     ( unamed_placeholder::make_partial_ap<unamed_placeholder::right<operators::name>>(boost::hof::decay(x)) ); \
0431     template<class T> \
0432     constexpr inline auto operator op (const T& x, const unamed_placeholder&) BOOST_HOF_RETURNS \
0433     ( unamed_placeholder::make_partial_ap<unamed_placeholder::left<operators::name>>(boost::hof::decay(x)) ); \
0434     constexpr inline auto operator op (const unamed_placeholder&, const unamed_placeholder&) BOOST_HOF_RETURNS \
0435     ( operators::name() );
0436 
0437 BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP)
0438 }
0439 
0440 namespace placeholders {
0441 BOOST_HOF_DECLARE_STATIC_VAR(_, detail::unamed_placeholder);
0442 }
0443 
0444 using placeholders::_;
0445 
0446 }} // namespace boost::hof
0447 
0448 namespace std {
0449     template<int N>
0450     struct is_placeholder<boost::hof::placeholder<N>>
0451     : std::integral_constant<int, N>
0452     {};
0453 }
0454 
0455 namespace boost {
0456 
0457     template<class T> 
0458     struct is_placeholder;
0459 
0460     template<int N>
0461     struct is_placeholder<boost::hof::placeholder<N>>
0462     : std::integral_constant<int, N>
0463     {};
0464 
0465 
0466 }
0467 
0468 #endif