Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (C) 2020 T. Zachary Laine
0002 // Copyright Louis Dionne 2013-2017
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 #ifndef BOOST_PARSER_TUPLE_HPP
0008 #define BOOST_PARSER_TUPLE_HPP
0009 
0010 #include <boost/parser/config.hpp>
0011 #include <boost/parser/detail/detection.hpp>
0012 
0013 #if BOOST_PARSER_USE_STD_TUPLE
0014 
0015 #include <tuple>
0016 
0017 #else
0018 
0019 // Silence very verbose warnings about std::is_pod/std::is_literal being
0020 // deprecated.
0021 #if defined(__GNUC__) || defined(__clang__)
0022 #    pragma GCC diagnostic push
0023 #    pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0024 #    pragma GCC diagnostic ignored "-Wunused-value"
0025 #endif
0026 #include <boost/hana.hpp>
0027 #if defined(__GNUC__) || defined(__clang__)
0028 #    pragma GCC diagnostic pop
0029 #endif
0030 
0031 #endif
0032 
0033 
0034 namespace boost { namespace parser {
0035 
0036     namespace detail {
0037         // to_int() and parse_llong() taken from boost/hana/bool.hpp.
0038         constexpr int to_int(char c)
0039         {
0040             int result = 0;
0041 
0042             if (c >= 'A' && c <= 'F') {
0043                 result = static_cast<int>(c) - static_cast<int>('A') + 10;
0044             } else if (c >= 'a' && c <= 'f') {
0045                 result = static_cast<int>(c) - static_cast<int>('a') + 10;
0046             } else {
0047                 result = static_cast<int>(c) - static_cast<int>('0');
0048             }
0049 
0050             return result;
0051         }
0052 
0053         template<std::size_t N>
0054         constexpr long long parse_llong(const char (&arr)[N])
0055         {
0056             long long base = 10;
0057             std::size_t offset = 0;
0058 
0059             if constexpr (N > 2) {
0060                 bool starts_with_zero = arr[0] == '0';
0061                 bool is_hex = starts_with_zero && arr[1] == 'x';
0062                 bool is_binary = starts_with_zero && arr[1] == 'b';
0063 
0064                 if (is_hex) {
0065                     // 0xDEADBEEF (hexadecimal)
0066                     base = 16;
0067                     offset = 2;
0068                 } else if (is_binary) {
0069                     // 0b101011101 (binary)
0070                     base = 2;
0071                     offset = 2;
0072                 } else if (starts_with_zero) {
0073                     // 012345 (octal)
0074                     base = 8;
0075                     offset = 1;
0076                 }
0077             }
0078 
0079             long long number = 0;
0080             long long multiplier = 1;
0081 
0082             for (std::size_t i = 0; i < N - offset; ++i) {
0083                 char c = arr[N - 1 - i];
0084                 if (c != '\'') { // skip digit separators
0085                     number += to_int(c) * multiplier;
0086                     multiplier *= base;
0087                 }
0088             }
0089 
0090             return number;
0091         }
0092     }
0093 
0094     /** The tuple template alias used within Boost.Parser.  This will be
0095         `boost::hana::tuple` if `BOOST_PARSER_USE_HANA_TUPLE` is defined, and
0096         `std::tuple` otherwise. */
0097 #if BOOST_PARSER_USE_STD_TUPLE
0098     template<typename... Args>
0099     using tuple = std::tuple<Args...>;
0100 #else
0101     template<typename... Args>
0102     using tuple = hana::tuple<Args...>;
0103 #endif
0104 
0105     /** A template alias that is `boost::hana::integral_constant<T, I>` if
0106         `BOOST_PARSER_USE_HANA_TUPLE` is defined, and
0107         `std::integral_constant<T, I>` otherwise. */
0108 #if BOOST_PARSER_USE_STD_TUPLE
0109     template<typename T, T I>
0110     using integral_constant = std::integral_constant<T, I>;
0111 #else
0112     template<typename T, T I>
0113     using integral_constant = hana::integral_constant<T, I>;
0114 #endif
0115 
0116     /** An accessor that returns a reference to the `I`-th data member of an
0117         aggregate struct or `boost::parser::tuple`. */
0118     template<typename T, typename U, U I>
0119     constexpr decltype(auto) get(T && x, integral_constant<U, I> i);
0120 
0121     /** A template alias that is `boost::hana::llong<I>` if
0122         `BOOST_PARSER_USE_HANA_TUPLE` is defined, and
0123         `std::integral_constant<long long, I>` otherwise. */
0124     template<long long I>
0125     using llong = integral_constant<long long, I>;
0126 
0127     namespace literals {
0128         /** A literal that can be used to concisely name `parser::llong`
0129             integral constants. */
0130         template<char... chars>
0131         constexpr auto operator""_c()
0132         {
0133             constexpr long long n =
0134                 detail::parse_llong<sizeof...(chars)>({chars...});
0135             return llong<n>{};
0136         }
0137     }
0138 
0139     namespace detail {
0140         /** A tuple accessor that returns a reference to the `I`-th element. */
0141         template<typename T, T I, typename... Args>
0142         constexpr decltype(auto)
0143         tuple_get(tuple<Args...> const & t, integral_constant<T, I>)
0144         {
0145 #if BOOST_PARSER_USE_STD_TUPLE
0146             return std::get<I>(t);
0147 #else
0148             return hana::at_c<I>(t);
0149 #endif
0150         }
0151 
0152         /** A tuple accessor that returns a reference to the `I`-th element. */
0153         template<typename T, T I, typename... Args>
0154         constexpr decltype(auto)
0155         tuple_get(tuple<Args...> & t, integral_constant<T, I>)
0156         {
0157 #if BOOST_PARSER_USE_STD_TUPLE
0158             return std::get<I>(t);
0159 #else
0160             return hana::at_c<I>(t);
0161 #endif
0162         }
0163 
0164         /** A tuple accessor that returns a reference to the `I`-th element. */
0165         template<typename T, T I, typename... Args>
0166         constexpr decltype(auto)
0167         tuple_get(tuple<Args...> && t, integral_constant<T, I>)
0168         {
0169 #if BOOST_PARSER_USE_STD_TUPLE
0170             return std::move(std::get<I>(t));
0171 #else
0172             return std::move(hana::at_c<I>(t));
0173 #endif
0174         }
0175 
0176         template<int N>
0177         struct ce_int
0178         {
0179             constexpr static int value = N;
0180         };
0181 
0182         struct whatever
0183         {
0184             int _;
0185             template<typename T>
0186             operator T() const && noexcept
0187             {
0188                 // Yuck.
0189                 std::remove_reference_t<T> * ptr = nullptr;
0190                 ptr += 1; // warning mitigation
0191                 return *ptr;
0192             }
0193         };
0194 
0195         template<typename T, int... Is>
0196         constexpr auto
0197             constructible_expr_impl(std::integer_sequence<int, Is...>)
0198                 -> decltype(T{whatever{Is}...}, ce_int<1>{});
0199 
0200         template<typename T, typename N>
0201         using constructible_expr = decltype(detail::constructible_expr_impl<T>(
0202             std::make_integer_sequence<int, N::value>()));
0203 
0204         template<typename T, int... Is>
0205         constexpr int struct_arity_impl(std::integer_sequence<int, Is...>)
0206         {
0207             return (
0208                 detected_or_t<ce_int<0>, constructible_expr, T, ce_int<Is>>::
0209                     value +
0210                 ... + 0);
0211         }
0212 
0213         // This often mistakenly returns 1 when you give it a struct with
0214         // private/protected members, because of copy/move construction.
0215         // Fortunately, we don't care -- we never assign from tuples of size
0216         // 1.
0217         template<typename T>
0218         constexpr int struct_arity_v =
0219             detail::struct_arity_impl<T>(std::make_integer_sequence<
0220                                          int,
0221                                          BOOST_PARSER_MAX_AGGREGATE_SIZE>()) -
0222             1;
0223 
0224         template<typename T>
0225         constexpr int tuple_size_ = -1;
0226 
0227         template<typename... Elems>
0228         constexpr int tuple_size_<tuple<Elems...>> = sizeof...(Elems);
0229 
0230         template<typename T, typename Tuple, int... Is>
0231         auto assign_tuple_to_aggregate(
0232             T & x, Tuple tup, std::integer_sequence<int, Is...>)
0233             -> decltype(x = T{parser::get(std::move(tup), llong<Is>{})...});
0234 
0235         template<typename T, typename Tuple, int... Is>
0236         auto tuple_to_aggregate(Tuple && tup, std::integer_sequence<int, Is...>)
0237             -> decltype(T{std::move(parser::get(tup, llong<Is>{}))...})
0238         {
0239             return T{std::move(parser::get(tup, llong<Is>{}))...};
0240         }
0241 
0242         template<typename T, typename Tuple>
0243         using tuple_to_aggregate_expr =
0244             decltype(detail::assign_tuple_to_aggregate(
0245                 std::declval<T &>(),
0246                 std::declval<Tuple>(),
0247                 std::make_integer_sequence<int, tuple_size_<Tuple>>()));
0248 
0249         template<typename Struct, typename Tuple>
0250         constexpr bool is_struct_assignable_v =
0251             struct_arity_v<Struct> == tuple_size_<Tuple>
0252                 ? is_detected_v<tuple_to_aggregate_expr, Struct, Tuple>
0253                 : false;
0254 
0255         template<int N>
0256         struct tie_aggregate_impl
0257         {
0258             template<typename T>
0259             static constexpr auto call(T & x)
0260             {
0261                 static_assert(
0262                     sizeof(T) && false,
0263                     "It looks like you're trying to use a struct larger than "
0264                     "the limit.");
0265             }
0266         };
0267 
0268         template<typename T>
0269         constexpr auto tie_aggregate(T & x)
0270         {
0271             static_assert(!std::is_union_v<T>);
0272             return tie_aggregate_impl<struct_arity_v<T>>::call(x);
0273         }
0274 
0275         template<typename Tuple, typename Tie, int... Is>
0276         auto aggregate_to_tuple(
0277             Tuple & tup, Tie tie, std::integer_sequence<int, Is...>)
0278             -> decltype((
0279                 (parser::get(tup, llong<Is>{}) =
0280                      std::move(parser::get(tie, llong<Is>{}))),
0281                 ...,
0282                 (void)0))
0283         {
0284             return (
0285                 (parser::get(tup, llong<Is>{}) =
0286                      std::move(parser::get(tie, llong<Is>{}))),
0287                 ...,
0288                 (void)0);
0289         }
0290 
0291         template<typename Tuple, typename T>
0292         using aggregate_to_tuple_expr = decltype(detail::aggregate_to_tuple(
0293             std::declval<Tuple &>(),
0294             detail::tie_aggregate(std::declval<T &>()),
0295             std::make_integer_sequence<int, tuple_size_<Tuple>>()));
0296 
0297         template<typename Tuple, typename Struct>
0298         constexpr bool is_tuple_assignable_impl()
0299         {
0300             if constexpr (
0301                 std::is_aggregate_v<Struct> &&
0302                 struct_arity_v<Struct> == tuple_size_<Tuple>) {
0303                 return is_detected_v<aggregate_to_tuple_expr, Tuple, Struct>;
0304             } else {
0305                 return false;
0306             }
0307         }
0308 
0309         template<typename Tuple, typename Struct>
0310         constexpr bool
0311             is_tuple_assignable_v = is_tuple_assignable_impl<Tuple, Struct>();
0312 
0313         template<typename T>
0314         struct is_tuple : std::false_type
0315         {};
0316         template<typename... T>
0317         struct is_tuple<tuple<T...>> : std::true_type
0318         {};
0319     }
0320 
0321     template<typename T, typename U, U I>
0322     constexpr decltype(auto) get(T && x, integral_constant<U, I> i)
0323     {
0324         using just_t = std::decay_t<T>;
0325         if constexpr (detail::is_tuple<just_t>::value) {
0326             return detail::tuple_get((T &&) x, i);
0327         } else if constexpr (std::is_aggregate_v<just_t>) {
0328             auto tup = detail::tie_aggregate(x);
0329             return detail::tuple_get(tup, i);
0330         } else {
0331             static_assert(
0332                 sizeof(T) != sizeof(T),
0333                 "boost::parser::get() is only defined for boost::parser::tuple "
0334                 "and aggregate structs.");
0335         }
0336     }
0337 
0338 }}
0339 
0340 #include <boost/parser/detail/aggr_to_tuple_generated.hpp>
0341 
0342 #endif