File indexing completed on 2025-09-17 08:40:36
0001
0002
0003
0004
0005
0006
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
0020
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
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
0066 base = 16;
0067 offset = 2;
0068 } else if (is_binary) {
0069
0070 base = 2;
0071 offset = 2;
0072 } else if (starts_with_zero) {
0073
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 != '\'') {
0085 number += to_int(c) * multiplier;
0086 multiplier *= base;
0087 }
0088 }
0089
0090 return number;
0091 }
0092 }
0093
0094
0095
0096
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
0106
0107
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
0117
0118 template<typename T, typename U, U I>
0119 constexpr decltype(auto) get(T && x, integral_constant<U, I> i);
0120
0121
0122
0123
0124 template<long long I>
0125 using llong = integral_constant<long long, I>;
0126
0127 namespace literals {
0128
0129
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
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
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
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
0189 std::remove_reference_t<T> * ptr = nullptr;
0190 ptr += 1;
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
0214
0215
0216
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