| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 | /*!@fileDefines `boost::hana::_`.@copyright Louis Dionne 2013-2017Distributed under the Boost Software License, Version 1.0.(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */#ifndef BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP#define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP#include <boost/hana/basic_tuple.hpp>#include <boost/hana/config.hpp>#include <boost/hana/detail/create.hpp>#include <boost/hana/detail/decay.hpp>#include <cstddef>#include <utility>BOOST_HANA_NAMESPACE_BEGIN    //! @ingroup group-functional    //! Create simple functions representing C++ operators inline.    //!    //! Specifically, `_` is an object used as a placeholder to build    //! function objects representing calls to C++ operators. It works    //! by overloading the operators between `_` and any object so that    //! they return a function object which actually calls the corresponding    //! operator on its argument(s). Hence, for any supported operator `@`:    //! @code    //!     (_ @ _)(x, y) == x @ y    //! @endcode    //!    //! Operators may also be partially applied to one argument inline:    //! @code    //!     (x @ _)(y) == x @ y    //!     (_ @ y)(x) == x @ y    //! @endcode    //!    //! When invoked with more arguments than required, functions created with    //! `_` will discard the superfluous instead of triggering an error:    //! @code    //!     (_ @ _)(x, y, z...) == x @ y    //! @endcode    //!    //! This makes functions created with `_` easier to use in higher-order    //! algorithms, which sometime provide more information than necessary    //! to their callbacks.    //!    //! ### Supported operators    //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`    //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`    //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`    //! - %Logical: `||`, `&&`, `!`    //! - Member access: `*` (dereference), `[]` (array subscript)    //! - Other: `()` (function call)    //!    //! More complex functionality like the ability to compose placeholders    //! into larger function objects inline are not supported. This is on    //! purpose; you should either use C++14 generic lambdas or a library    //! like [Boost.Phoenix][] if you need bigger guns. The goal here is    //! to save you a couple of characters in simple situations.    //!    //! ### Example    //! @include example/functional/placeholder.cpp    //!    //! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html#ifdef BOOST_HANA_DOXYGEN_INVOKED    constexpr unspecified _{};#else    namespace placeholder_detail {        template <typename I>        struct subscript {            I i;            template <typename Xs, typename ...Z>            constexpr auto operator()(Xs&& xs, Z const& ...) const&                -> decltype(static_cast<Xs&&>(xs)[i])            { return static_cast<Xs&&>(xs)[i]; }            template <typename Xs, typename ...Z>            constexpr auto operator()(Xs&& xs, Z const& ...) &                -> decltype(static_cast<Xs&&>(xs)[i])            { return static_cast<Xs&&>(xs)[i]; }            template <typename Xs, typename ...Z>            constexpr auto operator()(Xs&& xs, Z const& ...) &&                -> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])            { return static_cast<Xs&&>(xs)[std::move(i)]; }        };        template <typename F, typename Xs, std::size_t ...i>        constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {            return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);        }        template <typename ...X>        struct invoke;        struct placeholder {            struct secret { };            template <typename X>            constexpr decltype(auto) operator[](X&& x) const            { return detail::create<subscript>{}(static_cast<X&&>(x)); }            template <typename ...X>            constexpr invoke<typename detail::decay<X>::type...>            operator()(X&& ...x) const {                return {secret{}, static_cast<X&&>(x)...};            }        };        template <typename ...X>        struct invoke {            template <typename ...Y>            constexpr invoke(placeholder::secret, Y&& ...y)                : storage_{static_cast<Y&&>(y)...}            { }            basic_tuple<X...> storage_;            template <typename F, typename ...Z>            constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(                static_cast<F&&>(f)(std::declval<X const&>()...)            ) {                return invoke_impl(static_cast<F&&>(f), *this,                                   std::make_index_sequence<sizeof...(X)>{});            }            template <typename F, typename ...Z>            constexpr auto operator()(F&& f, Z const& ...) & -> decltype(                static_cast<F&&>(f)(std::declval<X&>()...)            ) {                return invoke_impl(static_cast<F&&>(f), *this,                                   std::make_index_sequence<sizeof...(X)>{});            }            template <typename F, typename ...Z>            constexpr auto operator()(F&& f, Z const& ...) && -> decltype(                static_cast<F&&>(f)(std::declval<X&&>()...)            ) {                return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),                                   std::make_index_sequence<sizeof...(X)>{});            }        };#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name)                           \    template <typename X>                                                       \    struct op_name ## _left {                                                   \        X x;                                                                    \                                                                                \        template <typename Y, typename ...Z>                                    \        constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype(      \            std::declval<X const&>() op static_cast<Y&&>(y))                    \        { return x op static_cast<Y&&>(y); }                                    \                                                                                \        template <typename Y, typename ...Z>                                    \        constexpr auto operator()(Y&& y, Z const& ...) & -> decltype(           \            std::declval<X&>() op static_cast<Y&&>(y))                          \        { return x op static_cast<Y&&>(y); }                                    \                                                                                \        template <typename Y, typename ...Z>                                    \        constexpr auto operator()(Y&& y, Z const& ...) && -> decltype(          \            std::declval<X>() op static_cast<Y&&>(y))                           \        { return std::move(x) op static_cast<Y&&>(y); }                         \    };                                                                          \                                                                                \    template <typename Y>                                                       \    struct op_name ## _right {                                                  \        Y y;                                                                    \                                                                                \        template <typename X, typename ...Z>                                    \        constexpr auto operator()(X&& x, Z const& ...) const& -> decltype(      \            static_cast<X&&>(x) op std::declval<Y const&>())                    \        { return static_cast<X&&>(x) op y; }                                    \                                                                                \        template <typename X, typename ...Z>                                    \        constexpr auto operator()(X&& x, Z const& ...) & -> decltype(           \            static_cast<X&&>(x) op std::declval<Y&>())                          \        { return static_cast<X&&>(x) op y; }                                    \                                                                                \        template <typename X, typename ...Z>                                    \        constexpr auto operator()(X&& x, Z const& ...) && -> decltype(          \            static_cast<X&&>(x) op std::declval<Y>())                           \        { return static_cast<X&&>(x) op std::move(y); }                         \    };                                                                          \                                                                                \    struct op_name {                                                            \        template <typename X, typename Y, typename ...Z>                        \        constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\            static_cast<X&&>(x) op static_cast<Y&&>(y))                         \        { return static_cast<X&&>(x) op static_cast<Y&&>(y); }                  \    };                                                                          \                                                                                \    template <typename X>                                                       \    constexpr decltype(auto) operator op (X&& x, placeholder)                   \    { return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); }         \                                                                                \    template <typename Y>                                                       \    constexpr decltype(auto) operator op (placeholder, Y&& y)                   \    { return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); }        \                                                                                \    inline constexpr decltype(auto) operator op (placeholder, placeholder)      \    { return op_name{}; }                                                       \/**/#define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name)                        \    struct op_name {                                                        \        template <typename X, typename ...Z>                                \        constexpr auto operator()(X&& x, Z const& ...) const                \            -> decltype(op static_cast<X&&>(x))                             \        { return op static_cast<X&&>(x); }                                  \    };                                                                      \                                                                            \    inline constexpr decltype(auto) operator op (placeholder)               \    { return op_name{}; }                                                   \/**/            // Arithmetic            BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)            BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)            BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)            BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)            BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)            BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)            BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)            // Bitwise            BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)            BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)            BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)            BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)            BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)            BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)            // Comparison            BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)            BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)            BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)            BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)            BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)            BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)            // Logical            BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)            BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)            BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)            // Member access (array subscript is a member function)            BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)            // Other (function call is a member function)#undef BOOST_HANA_PREFIX_PLACEHOLDER_OP#undef BOOST_HANA_BINARY_PLACEHOLDER_OP    } // end namespace placeholder_detail    constexpr placeholder_detail::placeholder _{};#endifBOOST_HANA_NAMESPACE_END#endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
 |