123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- /*=============================================================================
- Copyright (c) 2014 Paul Fultz II
- placeholders.h
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- ==============================================================================*/
- #ifndef BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
- #define BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
- /// placeholders
- /// ============
- ///
- /// Description
- /// -----------
- ///
- /// The placeholders provide `std::bind` compatible placeholders that
- /// additionally provide basic C++ operators that creates bind expressions.
- /// Each bind expression supports `constexpr` function evaluation.
- ///
- /// Synopsis
- /// --------
- ///
- /// namespace placeholders {
- /// placeholder<1> _1 = {};
- /// placeholder<2> _2 = {};
- /// placeholder<3> _3 = {};
- /// placeholder<4> _4 = {};
- /// placeholder<5> _5 = {};
- /// placeholder<6> _6 = {};
- /// placeholder<7> _7 = {};
- /// placeholder<8> _8 = {};
- /// placeholder<9> _9 = {};
- /// }
- ///
- /// Operators
- /// ---------
- ///
- /// * Binary operators: +,-,*,/,%,>>,<<,>,<,<=,>=,==,!=,&,^,|,&&,||
- /// * Assign operators: +=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=
- /// * Unary operators: !,~,+,-,*,++,--
- ///
- ///
- /// Example
- /// -------
- ///
- /// #include <boost/hof.hpp>
- /// #include <cassert>
- /// using namespace boost::hof;
- ///
- /// int main() {
- /// auto sum = _1 + _2;
- /// assert(3 == sum(1, 2));
- /// }
- ///
- ///
- /// unamed placeholder
- /// ==================
- ///
- /// Description
- /// -----------
- ///
- /// The unamed placeholder can be used to build simple functions from C++
- /// operators.
- ///
- /// Note: The function produced by the unamed placeholder is not a bind expression.
- ///
- /// Synopsis
- /// --------
- ///
- /// namespace placeholders {
- /// /* unspecified */ _ = {};
- /// }
- ///
- /// Example
- /// -------
- ///
- /// #include <boost/hof.hpp>
- /// #include <cassert>
- /// using namespace boost::hof;
- ///
- /// int main() {
- /// auto sum = _ + _;
- /// assert(3 == sum(1, 2));
- /// }
- ///
- #include <boost/hof/returns.hpp>
- #include <boost/hof/lazy.hpp>
- #include <boost/hof/protect.hpp>
- #if defined(_MSC_VER) && _MSC_VER >= 1910
- #include <boost/hof/detail/pp.hpp>
- #endif
- namespace boost { namespace hof { namespace detail {
- template<int N>
- struct simple_placeholder
- {};
- }}} // namespace boost::hof
- namespace std {
- template<int N>
- struct is_placeholder<boost::hof::detail::simple_placeholder<N>>
- : std::integral_constant<int, N>
- {};
- }
- namespace boost { namespace hof {
- #define BOOST_HOF_FOREACH_BINARY_OP(m) \
- m(+, add) \
- m(-, subtract) \
- m(*, multiply) \
- m(/, divide) \
- m(%, remainder) \
- m(>>, shift_right) \
- m(<<, shift_left) \
- m(>, greater_than) \
- m(<, less_than) \
- m(<=, less_than_equal) \
- m(>=, greater_than_equal) \
- m(==, equal) \
- m(!=, not_equal) \
- m(&, bit_and) \
- m(^, xor_) \
- m(|, bit_or) \
- m(&&, and_) \
- m(||, or_)
- #define BOOST_HOF_FOREACH_ASSIGN_OP(m) \
- m(+=, assign_add) \
- m(-=, assign_subtract) \
- m(*=, assign_multiply) \
- m(/=, assign_divide) \
- m(%=, assign_remainder) \
- m(>>=, assign_right_shift) \
- m(<<=, assign_left_shift) \
- m(&=, assign_bit_and) \
- m(|=, assign_bit_or) \
- m(^=, assign_xor)
- #ifndef _MSC_VER
- #define BOOST_HOF_FOREACH_UNARY_OP(m) \
- m(!, not_) \
- m(~, compl_) \
- m(+, unary_plus) \
- m(-, unary_subtract) \
- m(*, dereference) \
- m(++, increment) \
- m(--, decrement)
- #else
- #define BOOST_HOF_FOREACH_UNARY_OP(m) \
- m(!, not_) \
- m(~, compl_) \
- m(+, unary_plus) \
- m(-, unary_subtract) \
- m(*, dereference)
- #endif
- namespace operators {
- struct call
- {
- template<class F, class... Ts>
- constexpr auto operator()(F&& f, Ts&&... xs) const BOOST_HOF_RETURNS
- (f(BOOST_HOF_FORWARD(Ts)(xs)...));
- };
- // MSVC 2017 ICEs on && and || in conxtexpr, so we fallback on bitwise operators
- #if defined(_MSC_VER) && _MSC_VER >= 1910
- #define BOOST_HOF_BINARY_OP_SKIP_and_ ()
- #define BOOST_HOF_BINARY_OP_SKIP_or_ ()
- struct and_
- {
- template<class T, class U>
- constexpr auto operator()(T&& x, U&& y) const
- noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y)))
- -> decltype(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y))
- { return BOOST_HOF_FORWARD(T)(x) & BOOST_HOF_FORWARD(U)(y); }
- };
- struct or_
- {
- template<class T, class U>
- constexpr auto operator()(T&& x, U&& y) const
- noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y)))
- -> decltype(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y))
- { return BOOST_HOF_FORWARD(T)(x) | BOOST_HOF_FORWARD(U)(y); }
- };
- #define BOOST_HOF_BINARY_OP_IMPL(op, name) \
- struct name \
- { \
- template<class T, class U> \
- BOOST_HOF_USING(ex_failure, decltype(std::declval<T>() op std::declval<U>())); \
- struct failure : as_failure<ex_failure> {}; \
- template<class T, class U> \
- constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
- (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
- };
- #define BOOST_HOF_BINARY_OP(op, name) \
- BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_CAT(BOOST_HOF_BINARY_OP_SKIP_, name))) \
- (BOOST_HOF_PP_EMPTY, BOOST_HOF_BINARY_OP_IMPL)(op, name)
- #else
- #define BOOST_HOF_BINARY_OP(op, name) \
- struct name \
- { \
- template<class T, class U> \
- constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
- (BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
- };
- #endif
- BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_BINARY_OP)
- BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_BINARY_OP)
- #define BOOST_HOF_UNARY_OP(op, name) \
- struct name \
- { \
- template<class T> \
- constexpr auto operator()(T&& x) const BOOST_HOF_RETURNS \
- (op(BOOST_HOF_FORWARD(T)(x))); \
- };
- BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNARY_OP)
- }
- template<int N>
- struct placeholder
- {
- #if BOOST_HOF_HAS_MANGLE_OVERLOAD
- template<class... Ts>
- constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
- ( boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...) );
- #else
- template<class... Ts>
- struct result_call
- { typedef decltype(boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), std::declval<Ts>()...)) type; };
- template<class... Ts>
- constexpr typename result_call<Ts...>::type operator()(Ts&&... xs) const
- { return boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...); };
- #endif
- #define BOOST_HOF_PLACEHOLDER_UNARY_OP(op, name) \
- constexpr auto operator op () const BOOST_HOF_RETURNS \
- ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>()) );
- BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_PLACEHOLDER_UNARY_OP)
- #define BOOST_HOF_PLACEHOLDER_ASSIGN_OP(op, name) \
- template<class T> \
- constexpr auto operator op (T&& x) const BOOST_HOF_RETURNS \
- ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) );
- BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_PLACEHOLDER_ASSIGN_OP)
- };
- #if BOOST_HOF_HAS_MANGLE_OVERLOAD
- #define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
- template<class T, int N> \
- constexpr inline auto operator op (const placeholder<N>&, T&& x) BOOST_HOF_RETURNS \
- ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) ); \
- template<class T, int N> \
- constexpr inline auto operator op (T&& x, const placeholder<N>&) BOOST_HOF_RETURNS \
- ( boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()) ); \
- template<int N, int M> \
- constexpr inline auto operator op (const placeholder<N>&, const placeholder<M>&) BOOST_HOF_RETURNS \
- ( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()) );
- #else
- #define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
- template<class T, class U> \
- struct result_ ## name \
- { typedef decltype(boost::hof::lazy(operators::name())(std::declval<T>(), std::declval<U>())) type; }; \
- template<class T, int N> \
- constexpr inline typename result_ ## name<detail::simple_placeholder<N>, T>::type operator op (const placeholder<N>&, T&& x) \
- { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)); } \
- template<class T, int N> \
- constexpr inline typename result_ ## name<T, detail::simple_placeholder<N>>::type operator op (T&& x, const placeholder<N>&) \
- { return boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()); } \
- template<int N, int M> \
- constexpr inline typename result_ ## name<detail::simple_placeholder<N>, detail::simple_placeholder<M>>::type operator op (const placeholder<N>&, const placeholder<M>&) \
- { return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()); }
- #endif
- BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_PLACEHOLDER_BINARY_OP)
- namespace placeholders {
- BOOST_HOF_DECLARE_STATIC_VAR(_1, placeholder<1>);
- BOOST_HOF_DECLARE_STATIC_VAR(_2, placeholder<2>);
- BOOST_HOF_DECLARE_STATIC_VAR(_3, placeholder<3>);
- BOOST_HOF_DECLARE_STATIC_VAR(_4, placeholder<4>);
- BOOST_HOF_DECLARE_STATIC_VAR(_5, placeholder<5>);
- BOOST_HOF_DECLARE_STATIC_VAR(_6, placeholder<6>);
- BOOST_HOF_DECLARE_STATIC_VAR(_7, placeholder<7>);
- BOOST_HOF_DECLARE_STATIC_VAR(_8, placeholder<8>);
- BOOST_HOF_DECLARE_STATIC_VAR(_9, placeholder<9>);
- }
- using placeholders::_1;
- using placeholders::_2;
- using placeholders::_3;
- using placeholders::_4;
- using placeholders::_5;
- using placeholders::_6;
- using placeholders::_7;
- using placeholders::_8;
- using placeholders::_9;
- namespace detail {
- struct unamed_placeholder
- {
- template<class T, class Invoker>
- struct partial_ap
- {
- T val;
- BOOST_HOF_INHERIT_DEFAULT_EMPTY(partial_ap, T)
- template<class X, class... Xs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, X&&, Xs&&...)>
- constexpr partial_ap(X&& x, Xs&&... xs) : val(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Xs)(xs)...)
- {}
- BOOST_HOF_RETURNS_CLASS(partial_ap);
- struct partial_ap_failure
- {
- template<class Failure>
- struct apply
- {
- template<class... Xs>
- struct of;
- template<class X>
- struct of<X>
- : Failure::template of<typename std::add_const<T>::type, X>
- {};
- };
- };
- struct failure
- : failure_map<partial_ap_failure, Invoker>
- {};
- template<class X>
- constexpr BOOST_HOF_SFINAE_RESULT(const Invoker&, id_<T>, id_<X>)
- operator()(X&& x) const BOOST_HOF_SFINAE_RETURNS
- (
- Invoker()(BOOST_HOF_CONST_THIS->val, BOOST_HOF_FORWARD(X)(x))
- );
- };
- template<class Invoker, class T>
- static constexpr partial_ap<T, Invoker> make_partial_ap(T&& x)
- {
- return {BOOST_HOF_FORWARD(T)(x)};
- }
- template<class Op>
- struct left
- {
- struct failure
- : failure_for<Op>
- {};
- template<class T, class X>
- constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<T>, id_<X>)
- operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
- (Op()(BOOST_HOF_FORWARD(T)(val), BOOST_HOF_FORWARD(X)(x)));
- };
- template<class Op>
- struct right
- {
- struct right_failure
- {
- template<class Failure>
- struct apply
- {
- template<class T, class U, class... Ts>
- struct of
- : Failure::template of<U, T, Ts...>
- {};
- };
- };
- struct failure
- : failure_map<right_failure, Op>
- {};
- template<class T, class X>
- constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<X>, id_<T>)
- operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
- (Op()(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(T)(val)));
- };
- #define BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP(op, name) \
- constexpr auto operator op () const BOOST_HOF_RETURNS \
- ( operators::name() );
- BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP)
- #define BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP(op, name) \
- template<class T> \
- constexpr auto operator op (const T& x) const BOOST_HOF_RETURNS \
- ( partial_ap<T, left<operators::name>>(x) );
- BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP)
- };
- #define BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP(op, name) \
- template<class T> \
- constexpr inline auto operator op (const unamed_placeholder&, const T& x) BOOST_HOF_RETURNS \
- ( unamed_placeholder::make_partial_ap<unamed_placeholder::right<operators::name>>(boost::hof::decay(x)) ); \
- template<class T> \
- constexpr inline auto operator op (const T& x, const unamed_placeholder&) BOOST_HOF_RETURNS \
- ( unamed_placeholder::make_partial_ap<unamed_placeholder::left<operators::name>>(boost::hof::decay(x)) ); \
- constexpr inline auto operator op (const unamed_placeholder&, const unamed_placeholder&) BOOST_HOF_RETURNS \
- ( operators::name() );
- BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP)
- }
- namespace placeholders {
- BOOST_HOF_DECLARE_STATIC_VAR(_, detail::unamed_placeholder);
- }
- using placeholders::_;
- }} // namespace boost::hof
- namespace std {
- template<int N>
- struct is_placeholder<boost::hof::placeholder<N>>
- : std::integral_constant<int, N>
- {};
- }
- namespace boost {
- template<class T>
- struct is_placeholder;
- template<int N>
- struct is_placeholder<boost::hof::placeholder<N>>
- : std::integral_constant<int, N>
- {};
- }
- #endif
|