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:
2448
include/boost/parser/detail/aggr_to_tuple_generated.hpp
Normal file
2448
include/boost/parser/detail/aggr_to_tuple_generated.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
58
misc/generate_aggr_to_tuple.py
Executable 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')
|
||||
Reference in New Issue
Block a user