Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:58

0001 /*!
0002 @file
0003 Defines `boost::hana::_`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
0011 #define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
0012 
0013 #include <boost/hana/basic_tuple.hpp>
0014 #include <boost/hana/config.hpp>
0015 #include <boost/hana/detail/create.hpp>
0016 #include <boost/hana/detail/decay.hpp>
0017 
0018 #include <cstddef>
0019 #include <utility>
0020 
0021 
0022 namespace boost { namespace hana {
0023     //! @ingroup group-functional
0024     //! Create simple functions representing C++ operators inline.
0025     //!
0026     //! Specifically, `_` is an object used as a placeholder to build
0027     //! function objects representing calls to C++ operators. It works
0028     //! by overloading the operators between `_` and any object so that
0029     //! they return a function object which actually calls the corresponding
0030     //! operator on its argument(s). Hence, for any supported operator `@`:
0031     //! @code
0032     //!     (_ @ _)(x, y) == x @ y
0033     //! @endcode
0034     //!
0035     //! Operators may also be partially applied to one argument inline:
0036     //! @code
0037     //!     (x @ _)(y) == x @ y
0038     //!     (_ @ y)(x) == x @ y
0039     //! @endcode
0040     //!
0041     //! When invoked with more arguments than required, functions created with
0042     //! `_` will discard the superfluous instead of triggering an error:
0043     //! @code
0044     //!     (_ @ _)(x, y, z...) == x @ y
0045     //! @endcode
0046     //!
0047     //! This makes functions created with `_` easier to use in higher-order
0048     //! algorithms, which sometime provide more information than necessary
0049     //! to their callbacks.
0050     //!
0051     //! ### Supported operators
0052     //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
0053     //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
0054     //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
0055     //! - %Logical: `||`, `&&`, `!`
0056     //! - Member access: `*` (dereference), `[]` (array subscript)
0057     //! - Other: `()` (function call)
0058     //!
0059     //! More complex functionality like the ability to compose placeholders
0060     //! into larger function objects inline are not supported. This is on
0061     //! purpose; you should either use C++14 generic lambdas or a library
0062     //! like [Boost.Phoenix][] if you need bigger guns. The goal here is
0063     //! to save you a couple of characters in simple situations.
0064     //!
0065     //! ### Example
0066     //! @include example/functional/placeholder.cpp
0067     //!
0068     //! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
0069 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0070     constexpr unspecified _{};
0071 #else
0072     namespace placeholder_detail {
0073         template <typename I>
0074         struct subscript {
0075             I i;
0076 
0077             template <typename Xs, typename ...Z>
0078             constexpr auto operator()(Xs&& xs, Z const& ...) const&
0079                 -> decltype(static_cast<Xs&&>(xs)[i])
0080             { return static_cast<Xs&&>(xs)[i]; }
0081 
0082             template <typename Xs, typename ...Z>
0083             constexpr auto operator()(Xs&& xs, Z const& ...) &
0084                 -> decltype(static_cast<Xs&&>(xs)[i])
0085             { return static_cast<Xs&&>(xs)[i]; }
0086 
0087             template <typename Xs, typename ...Z>
0088             constexpr auto operator()(Xs&& xs, Z const& ...) &&
0089                 -> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
0090             { return static_cast<Xs&&>(xs)[std::move(i)]; }
0091         };
0092 
0093         template <typename F, typename Xs, std::size_t ...i>
0094         constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
0095             return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);
0096         }
0097 
0098         template <typename ...X>
0099         struct invoke;
0100 
0101         struct placeholder {
0102             struct secret { };
0103 
0104             template <typename X>
0105             constexpr decltype(auto) operator[](X&& x) const
0106             { return detail::create<subscript>{}(static_cast<X&&>(x)); }
0107 
0108             template <typename ...X>
0109             constexpr invoke<typename detail::decay<X>::type...>
0110             operator()(X&& ...x) const {
0111                 return {secret{}, static_cast<X&&>(x)...};
0112             }
0113         };
0114 
0115         template <typename ...X>
0116         struct invoke {
0117             template <typename ...Y>
0118             constexpr invoke(placeholder::secret, Y&& ...y)
0119                 : storage_{static_cast<Y&&>(y)...}
0120             { }
0121 
0122             basic_tuple<X...> storage_;
0123 
0124             template <typename F, typename ...Z>
0125             constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
0126                 static_cast<F&&>(f)(std::declval<X const&>()...)
0127             ) {
0128                 return invoke_impl(static_cast<F&&>(f), *this,
0129                                    std::make_index_sequence<sizeof...(X)>{});
0130             }
0131 
0132             template <typename F, typename ...Z>
0133             constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
0134                 static_cast<F&&>(f)(std::declval<X&>()...)
0135             ) {
0136                 return invoke_impl(static_cast<F&&>(f), *this,
0137                                    std::make_index_sequence<sizeof...(X)>{});
0138             }
0139 
0140             template <typename F, typename ...Z>
0141             constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
0142                 static_cast<F&&>(f)(std::declval<X&&>()...)
0143             ) {
0144                 return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
0145                                    std::make_index_sequence<sizeof...(X)>{});
0146             }
0147         };
0148 
0149 #define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name)                           \
0150     template <typename X>                                                       \
0151     struct op_name ## _left {                                                   \
0152         X x;                                                                    \
0153                                                                                 \
0154         template <typename Y, typename ...Z>                                    \
0155         constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype(      \
0156             std::declval<X const&>() op static_cast<Y&&>(y))                    \
0157         { return x op static_cast<Y&&>(y); }                                    \
0158                                                                                 \
0159         template <typename Y, typename ...Z>                                    \
0160         constexpr auto operator()(Y&& y, Z const& ...) & -> decltype(           \
0161             std::declval<X&>() op static_cast<Y&&>(y))                          \
0162         { return x op static_cast<Y&&>(y); }                                    \
0163                                                                                 \
0164         template <typename Y, typename ...Z>                                    \
0165         constexpr auto operator()(Y&& y, Z const& ...) && -> decltype(          \
0166             std::declval<X>() op static_cast<Y&&>(y))                           \
0167         { return std::move(x) op static_cast<Y&&>(y); }                         \
0168     };                                                                          \
0169                                                                                 \
0170     template <typename Y>                                                       \
0171     struct op_name ## _right {                                                  \
0172         Y y;                                                                    \
0173                                                                                 \
0174         template <typename X, typename ...Z>                                    \
0175         constexpr auto operator()(X&& x, Z const& ...) const& -> decltype(      \
0176             static_cast<X&&>(x) op std::declval<Y const&>())                    \
0177         { return static_cast<X&&>(x) op y; }                                    \
0178                                                                                 \
0179         template <typename X, typename ...Z>                                    \
0180         constexpr auto operator()(X&& x, Z const& ...) & -> decltype(           \
0181             static_cast<X&&>(x) op std::declval<Y&>())                          \
0182         { return static_cast<X&&>(x) op y; }                                    \
0183                                                                                 \
0184         template <typename X, typename ...Z>                                    \
0185         constexpr auto operator()(X&& x, Z const& ...) && -> decltype(          \
0186             static_cast<X&&>(x) op std::declval<Y>())                           \
0187         { return static_cast<X&&>(x) op std::move(y); }                         \
0188     };                                                                          \
0189                                                                                 \
0190     struct op_name {                                                            \
0191         template <typename X, typename Y, typename ...Z>                        \
0192         constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
0193             static_cast<X&&>(x) op static_cast<Y&&>(y))                         \
0194         { return static_cast<X&&>(x) op static_cast<Y&&>(y); }                  \
0195     };                                                                          \
0196                                                                                 \
0197     template <typename X>                                                       \
0198     constexpr decltype(auto) operator op (X&& x, placeholder)                   \
0199     { return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); }         \
0200                                                                                 \
0201     template <typename Y>                                                       \
0202     constexpr decltype(auto) operator op (placeholder, Y&& y)                   \
0203     { return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); }        \
0204                                                                                 \
0205     inline constexpr decltype(auto) operator op (placeholder, placeholder)      \
0206     { return op_name{}; }                                                       \
0207 /**/
0208 
0209 #define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name)                        \
0210     struct op_name {                                                        \
0211         template <typename X, typename ...Z>                                \
0212         constexpr auto operator()(X&& x, Z const& ...) const                \
0213             -> decltype(op static_cast<X&&>(x))                             \
0214         { return op static_cast<X&&>(x); }                                  \
0215     };                                                                      \
0216                                                                             \
0217     inline constexpr decltype(auto) operator op (placeholder)               \
0218     { return op_name{}; }                                                   \
0219 /**/
0220             // Arithmetic
0221             BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
0222             BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
0223             BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
0224             BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
0225             BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
0226             BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
0227             BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
0228 
0229             // Bitwise
0230             BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
0231             BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
0232             BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
0233             BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
0234             BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
0235             BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
0236 
0237             // Comparison
0238             BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
0239             BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
0240             BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
0241             BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
0242             BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
0243             BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
0244 
0245             // Logical
0246             BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
0247             BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
0248             BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
0249 
0250             // Member access (array subscript is a member function)
0251             BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
0252 
0253             // Other (function call is a member function)
0254 
0255 #undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
0256 #undef BOOST_HANA_BINARY_PLACEHOLDER_OP
0257     } // end namespace placeholder_detail
0258 
0259     BOOST_HANA_INLINE_VARIABLE constexpr placeholder_detail::placeholder _{};
0260 #endif
0261 }} // end namespace boost::hana
0262 
0263 #endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP