2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00

Add initial sketch of struct -> tuple assignment machinery.

Partially addresses #28.
This commit is contained in:
Zach Laine
2023-12-30 02:58:08 -06:00
parent 669af7fa69
commit 95374a7878
3 changed files with 2539 additions and 7 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -189,7 +189,7 @@ namespace boost { namespace parser {
-> decltype(T{whatever{Is}...}, ce_int<1>{});
template<typename T, typename N>
using constructible_expr = decltype(constructible_expr_impl<T>(
using constructible_expr = decltype(detail::constructible_expr_impl<T>(
std::make_integer_sequence<int, N::value>()));
template<typename T, int... Is>
@@ -206,8 +206,10 @@ namespace boost { namespace parser {
// Fortunately, we don't care -- we never assign from tuples of size
// 1.
template<typename T>
constexpr int struct_arity_v =
struct_arity_impl<T>(std::make_integer_sequence<int, 256>()) - 1;
constexpr int
struct_arity_v = detail::struct_arity_impl<T>(
std::make_integer_sequence<int, 100>()) -
1;
template<typename T>
constexpr int tuple_size_ = -1;
@@ -224,18 +226,42 @@ namespace boost { namespace parser {
}
template<typename T, typename Tuple>
using initialize_from_tuple_expr = decltype(initialize_from_tuple(
std::declval<T &>(),
std::declval<Tuple>(),
std::make_integer_sequence<int, tuple_size_<Tuple>>()));
using initialize_from_tuple_expr =
decltype(detail::initialize_from_tuple(
std::declval<T &>(),
std::declval<Tuple>(),
std::make_integer_sequence<int, tuple_size_<Tuple>>()));
template<typename Struct, typename Tuple>
constexpr bool is_struct_assignable_v =
struct_arity_v<Struct> == tuple_size_<Tuple>
? is_detected_v<initialize_from_tuple_expr, Struct, Tuple>
: false;
template<int N>
struct aggregate_to_tuple_impl
{
template<typename T>
static constexpr auto call(T x)
{
static_assert(
sizeof(T) && false,
"It looks like you're trying to use a struct larger than "
"the limit.");
}
};
template<typename T>
constexpr auto aggregate_to_tuple(T x)
{
static_assert(!std::is_union_v<T>);
return aggregate_to_tuple_impl<struct_arity_v<T>>::call(
std::move(x));
}
}
}}
#include <boost/parser/detail/aggr_to_tuple_generated.hpp>
#endif

58
misc/generate_aggr_to_tuple.py Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/python3
# Copyright (c) 2023 T. Zachary Laine
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
print('''// Copyright (c) 2023 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Warning: This header is auto-generated (see misc/generate_aggr_to_tuple.py).
// The lack of include guards is intentional.
namespace boost::parser::detail {
''')
specializations = 100
bindings = []
def bindings_str(fn, max_bindings_on_a_line):
num_bindings = len(bindings)
mapped = map(fn, bindings)
retval = ''
for i in range(int(num_bindings / max_bindings_on_a_line) + 1):
lo = i * max_bindings_on_a_line
if num_bindings <= lo:
return retval
hi = min(lo + max_bindings_on_a_line, num_bindings)
retval += ' ' + ', '.join(map(fn, bindings[lo:hi]))
if hi < num_bindings:
retval += ','
retval += '\n'
return retval
def destructuring_str():
return f'''auto & [
{bindings_str(lambda x: x, 15)}] = x;'''
def initializers_str():
return f'''return parser::tuple(
{bindings_str(lambda x: f'std::move({x})', 5)});'''
for i in range(1, specializations + 1):
bindings.append('_{:02x}'.format(i))
print(f'''template<> struct aggregate_to_tuple_impl<{i}> {{
template<typename T> static constexpr auto call(T x) {{''')
print(destructuring_str())
print(initializers_str())
print('''}
};
''')
print('}\n')