Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:27

0001 // Copyright (C) 2020 T. Zachary Laine
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
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     // Boost.Hana lite.  These functions work with boost::hana::tuple and
0020     // std::tuple.
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         // Hana's concat does not seem to do what it says on the tin.
0054         // Concatenating (int, string) with (double, int) yields (int, string,
0055         // double).  I maybe don't understand it well enough.
0056         return hana::insert_range(t1, hana::size(t1), t2);
0057 #endif
0058     }
0059 
0060 
0061     // apply
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     // for_each
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     // transform
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     // fold_left
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     // size
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     // contains
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     // front, back
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     // drop_front
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     // drop_back
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     // first, second
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     // zip
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     // append
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     // prepend
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