File indexing completed on 2025-09-17 08:40:27
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PARSER_DETAIL_HL_HPP
0007 #define BOOST_PARSER_DETAIL_HL_HPP
0008
0009 #include <boost/parser/config.hpp>
0010 #include <boost/parser/tuple.hpp>
0011 #include <boost/parser/detail/detection.hpp>
0012
0013 #include <type_traits>
0014 #include <utility>
0015
0016
0017 namespace boost { namespace parser { namespace detail::hl {
0018
0019
0020
0021
0022 struct forward
0023 {
0024 template<typename T>
0025 decltype(auto) operator()(T && t)
0026 {
0027 return (T &&) t;
0028 }
0029 };
0030
0031 template<typename... Args>
0032 constexpr auto make_tuple(Args &&... args)
0033 {
0034 #if BOOST_PARSER_USE_STD_TUPLE
0035 return std::make_tuple((Args &&) args...);
0036 #else
0037 return hana::make_tuple((Args &&) args...);
0038 #endif
0039 }
0040
0041 template<typename T, typename U>
0042 constexpr auto make_pair(T && t, U && u)
0043 {
0044 return hl::make_tuple((T &&) t, (U &&) u);
0045 }
0046
0047 template<typename Tuple1, typename Tuple2>
0048 constexpr auto concat(Tuple1 const & t1, Tuple2 const & t2)
0049 {
0050 #if BOOST_PARSER_USE_STD_TUPLE
0051 return std::tuple_cat(t1, t2);
0052 #else
0053
0054
0055
0056 return hana::insert_range(t1, hana::size(t1), t2);
0057 #endif
0058 }
0059
0060
0061
0062
0063 template<typename F, typename Tuple, std::size_t... I>
0064 constexpr auto
0065 apply_impl(F && f, Tuple && t, std::integer_sequence<std::size_t, I...>)
0066 -> decltype(((F &&) f)(parser::get((Tuple &&) t, llong<I>{})...))
0067 {
0068 return ((F &&) f)(parser::get((Tuple &&) t, llong<I>{})...);
0069 }
0070 template<
0071 typename F,
0072 typename Tuple,
0073 typename Enable = std::enable_if_t<detail::is_tuple<
0074 std::remove_cv_t<std::remove_reference_t<Tuple>>>{}>>
0075 constexpr auto apply(F && f, Tuple && t) -> decltype(hl::apply_impl(
0076 (F &&) f,
0077 (Tuple &&) t,
0078 std::make_integer_sequence<std::size_t, tuple_size_<Tuple>>{}))
0079 {
0080 return hl::apply_impl(
0081 (F &&) f,
0082 (Tuple &&) t,
0083 std::make_integer_sequence<std::size_t, tuple_size_<Tuple>>{});
0084 }
0085
0086
0087
0088
0089 template<typename F, typename Tuple, std::size_t... I>
0090 constexpr void for_each_impl(
0091 Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
0092 {
0093 int _[] = {0, (f(parser::get(t, llong<I>{})), 0)...};
0094 (void)_;
0095 }
0096 template<
0097 typename F,
0098 typename Tuple,
0099 std::size_t... I,
0100 typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
0101 constexpr void
0102 for_each_impl(Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
0103 {
0104 int _[] = {0, (f(std::move(parser::get(t, llong<I>{}))), 0)...};
0105 (void)_;
0106 }
0107
0108 template<typename F, typename... Args>
0109 constexpr void for_each(tuple<Args...> && t, F && f)
0110 {
0111 hl::for_each_impl(
0112 std::move(t),
0113 (F &&) f,
0114 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0115 }
0116 template<typename F, typename... Args>
0117 constexpr void for_each(tuple<Args...> const & t, F && f)
0118 {
0119 hl::for_each_impl(
0120 t,
0121 (F &&) f,
0122 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0123 }
0124
0125
0126
0127
0128 template<int offset, typename F, typename Tuple, std::size_t... I>
0129 constexpr auto transform_impl(
0130 Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
0131 {
0132 return tuple<
0133 std::decay_t<decltype(f(parser::get(t, llong<I + offset>{})))>...>{
0134 f(parser::get(t, llong<I + offset>{}))...};
0135 }
0136 template<
0137 int offset,
0138 typename F,
0139 typename Tuple,
0140 std::size_t... I,
0141 typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
0142 auto constexpr transform_impl(
0143 Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
0144 {
0145 return tuple<std::decay_t<decltype(
0146 f(std::move(parser::get(t, llong<I + offset>{}))))>...>{
0147 f(std::move(parser::get(t, llong<I + offset>{})))...};
0148 }
0149
0150 template<typename F, typename... Args>
0151 constexpr auto transform(tuple<Args...> && t, F && f)
0152 {
0153 return hl::transform_impl<0>(
0154 std::move(t),
0155 (F &&) f,
0156 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0157 }
0158 template<typename F, typename... Args>
0159 constexpr auto transform(tuple<Args...> const & t, F && f)
0160 {
0161 return hl::transform_impl<0>(
0162 t,
0163 (F &&) f,
0164 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0165 }
0166
0167
0168
0169
0170 template<std::size_t I, std::size_t N>
0171 struct fold_left_dispatch
0172 {
0173 template<typename F, typename State, typename... Args>
0174 constexpr static auto
0175 call(tuple<Args...> const & t, State && s, F const & f)
0176 {
0177 return fold_left_dispatch<I + 1, N>::call(
0178 t, f((State &&) s, parser::get(t, llong<I>{})), f);
0179 }
0180 };
0181 template<std::size_t I>
0182 struct fold_left_dispatch<I, I>
0183 {
0184 template<typename F, typename State, typename... Args>
0185 constexpr static auto
0186 call(tuple<Args...> const & t, State && s, F const & f)
0187 {
0188 return (State &&) s;
0189 }
0190 };
0191
0192 template<typename F, typename State, typename... Args>
0193 constexpr auto fold_left(tuple<Args...> const & t, State && s, F const & f)
0194 {
0195 return hl::fold_left_dispatch<0, sizeof...(Args)>::call(
0196 t, (State &&) s, (F &&) f);
0197 }
0198
0199
0200
0201
0202 template<typename... Args>
0203 constexpr auto size(tuple<Args...> const & t)
0204 {
0205 return llong<sizeof...(Args)>{};
0206 }
0207
0208 template<typename... Args>
0209 constexpr auto size_minus_one(tuple<Args...> const & t)
0210 {
0211 return llong<sizeof...(Args) - 1>{};
0212 }
0213
0214
0215
0216
0217 template<typename T, typename U>
0218 using comparable = decltype(std::declval<T>() == std::declval<U>());
0219
0220 struct typesafe_equals
0221 {
0222 template<typename T, typename U>
0223 constexpr bool operator()(T const & t, U const & u)
0224 {
0225 if constexpr (detail::is_detected_v<comparable, T, U>) {
0226 return t == u;
0227 } else {
0228 return false;
0229 }
0230 }
0231 };
0232
0233 template<typename T, typename Tuple, std::size_t... I>
0234 constexpr bool contains_impl(
0235 Tuple const & t, T const & x, std::integer_sequence<std::size_t, I...>)
0236 {
0237 typesafe_equals eq;
0238 (void)eq;
0239 return (eq(parser::get(t, llong<I>{}), x) || ...);
0240 }
0241
0242 template<typename T, typename... Args>
0243 constexpr bool contains(tuple<Args...> const & t, T const & x)
0244 {
0245 return contains_impl(
0246 t, x, std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0247 }
0248
0249
0250
0251
0252 template<typename Arg, typename... Args>
0253 constexpr decltype(auto) front(tuple<Arg, Args...> const & t)
0254 {
0255 return parser::get(t, llong<0>{});
0256 }
0257 template<typename Arg, typename... Args>
0258 constexpr decltype(auto) back(tuple<Arg, Args...> const & t)
0259 {
0260 return parser::get(t, llong<sizeof...(Args)>{});
0261 }
0262
0263
0264
0265
0266 template<typename Arg, typename... Args>
0267 constexpr auto drop_front(tuple<Arg, Args...> && t)
0268 {
0269 return hl::transform_impl<1>(
0270 std::move(t),
0271 forward{},
0272 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0273 }
0274 template<typename Arg, typename... Args>
0275 constexpr auto drop_front(tuple<Arg, Args...> const & t)
0276 {
0277 return hl::transform_impl<1>(
0278 t,
0279 forward{},
0280 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0281 }
0282
0283
0284
0285
0286 template<typename Arg, typename... Args>
0287 constexpr auto drop_back(tuple<Arg, Args...> && t)
0288 {
0289 return hl::transform_impl<0>(
0290 std::move(t),
0291 forward{},
0292 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0293 }
0294 template<typename Arg, typename... Args>
0295 constexpr auto drop_back(tuple<Arg, Args...> const & t)
0296 {
0297 return hl::transform_impl<0>(
0298 t,
0299 forward{},
0300 std::make_integer_sequence<std::size_t, sizeof...(Args)>());
0301 }
0302
0303
0304
0305
0306 template<typename T, typename U>
0307 constexpr decltype(auto) first(tuple<T, U> const & t)
0308 {
0309 return parser::get(t, llong<0>{});
0310 }
0311 template<typename T, typename U>
0312 constexpr decltype(auto) second(tuple<T, U> const & t)
0313 {
0314 return parser::get(t, llong<1>{});
0315 }
0316
0317
0318
0319
0320 template<std::size_t I, typename... Tuples>
0321 constexpr decltype(auto) make_zip_elem(Tuples const &... ts)
0322 {
0323 return hl::make_tuple(parser::get(ts, llong<I>{})...);
0324 }
0325
0326 template<std::size_t... I, typename... Tuples>
0327 constexpr auto zip_impl(std::index_sequence<I...>, Tuples const &... ts)
0328 {
0329 return hl::make_tuple(hl::make_zip_elem<I>(ts...)...);
0330 }
0331
0332 template<typename T>
0333 struct tuplesize;
0334 template<typename... Args>
0335 struct tuplesize<tuple<Args...>>
0336 {
0337 constexpr static std::size_t value = sizeof...(Args);
0338 };
0339
0340 template<typename Tuple, typename... Tuples>
0341 constexpr auto zip(Tuple const & t, Tuples const &... ts)
0342 {
0343 return hl::zip_impl(
0344 std::make_integer_sequence<
0345 std::size_t,
0346 tuplesize<std::remove_reference_t<Tuple>>::value>(),
0347 t,
0348 ts...);
0349 }
0350
0351
0352
0353
0354 template<typename... Args, typename T>
0355 constexpr auto append(tuple<Args...> && t, T && x)
0356 {
0357 #if BOOST_PARSER_USE_STD_TUPLE
0358 return std::tuple_cat(std::move(t), std::make_tuple((T &&) x));
0359 #else
0360 return hana::append(std::move(t), (T &&) x);
0361 #endif
0362 }
0363 template<typename... Args, typename T>
0364 constexpr auto append(tuple<Args...> const & t, T && x)
0365 {
0366 #if BOOST_PARSER_USE_STD_TUPLE
0367 return std::tuple_cat(t, std::make_tuple((T &&) x));
0368 #else
0369 return hana::append(t, (T &&) x);
0370 #endif
0371 }
0372
0373
0374
0375
0376 template<typename... Args, typename T>
0377 constexpr auto prepend(tuple<Args...> && t, T && x)
0378 {
0379 #if BOOST_PARSER_USE_STD_TUPLE
0380 return std::tuple_cat(std::make_tuple((T &&) x), std::move(t));
0381 #else
0382 return hana::prepend(std::move(t), (T &&) x);
0383 #endif
0384 }
0385 template<typename... Args, typename T>
0386 constexpr auto prepend(tuple<Args...> const & t, T && x)
0387 {
0388 #if BOOST_PARSER_USE_STD_TUPLE
0389 return std::tuple_cat(std::make_tuple((T &&) x), t);
0390 #else
0391 return hana::prepend(t, (T &&) x);
0392 #endif
0393 }
0394
0395 }}}
0396
0397 #endif