File indexing completed on 2025-01-18 09:37:58
0001
0002
0003
0004
0005
0006
0007
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
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
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
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
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
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
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
0251 BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
0252
0253
0254
0255 #undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
0256 #undef BOOST_HANA_BINARY_PLACEHOLDER_OP
0257 }
0258
0259 BOOST_HANA_INLINE_VARIABLE constexpr placeholder_detail::placeholder _{};
0260 #endif
0261 }}
0262
0263 #endif