1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
#!/usr/bin/python
# Copyright (c) 2016-2025 Antony Polukhin
# Copyright (c) 2023 Denis Mikhailov
#
# 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)
############################################################################################################################
import sys
import string
# Skipping some letters that may produce keywords or are hard to read, or shadow template parameters
ascii_letters = string.ascii_letters.replace("o", "").replace("O", "").replace("i", "").replace("I", "").replace("T", "")
WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE = 3
PROLOGUE = """// Copyright (c) 2016-2025 Antony Polukhin
// Copyright (c) 2023 Denis Mikhailov
//
// 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)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////// THIS HEADER IS AUTO GENERATED BY misc/generate_cpp17.py ////////////////
//////////////// MODIFY AND RUN THE misc/generate_cpp17.py INSTEAD OF DIRECTLY MODIFYING THE GENERATED FILE ////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_PFR_DETAIL_CORE17_GENERATED_HPP
#define BOOST_PFR_DETAIL_CORE17_GENERATED_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#if !BOOST_PFR_USE_CPP17
# error C++17 is required for this header.
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/size_t_.hpp>
#if !defined(BOOST_PFR_INTERFACE_UNIT)
#include <type_traits> // for std::conditional_t, std::is_reference
#endif
namespace boost { namespace pfr { namespace detail {
template <class... Args>
constexpr auto make_tuple_of_references(Args&&... args) noexcept {
return sequence_tuple::tuple<Args&...>{ args... };
}
template<typename T, typename Arg>
constexpr decltype(auto) add_cv_like(Arg& arg) noexcept {
if constexpr (std::is_const<T>::value && std::is_volatile<T>::value) {
return const_cast<const volatile Arg&>(arg);
}
else if constexpr (std::is_const<T>::value) {
return const_cast<const Arg&>(arg);
}
else if constexpr (std::is_volatile<T>::value) {
return const_cast<volatile Arg&>(arg);
}
else {
return const_cast<Arg&>(arg);
}
}
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78939
template<typename T, typename Sb, typename Arg>
constexpr decltype(auto) workaround_cast(Arg& arg) noexcept {
using output_arg_t = std::conditional_t<!std::is_reference<Sb>(), decltype(detail::add_cv_like<T>(arg)), Sb>;
return const_cast<output_arg_t>(arg);
}
template <class T>
constexpr auto tie_as_tuple(T& /*val*/, size_t_<0>) noexcept {
return sequence_tuple::tuple<>{};
}
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
auto& [a] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.
return ::boost::pfr::detail::make_tuple_of_references(detail::workaround_cast<T, decltype(a)>(a));
}
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<!std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
return ::boost::pfr::detail::make_tuple_of_references( val );
}
"""
############################################################################################################################
EPILOGUE = """
template <class T, std::size_t I>
constexpr void tie_as_tuple(T& /*val*/, size_t_<I>) noexcept {
static_assert(sizeof(T) && false,
"====================> Boost.PFR: Too many fields in a structure T. Regenerate include/boost/pfr/detail/core17_generated.hpp file for appropriate count of fields. For example: `python ./misc/generate_cpp17.py 300 > include/boost/pfr/detail/core17_generated.hpp`");
}
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CORE17_GENERATED_HPP
"""
############################################################################################################################
def fold_workaround_cast(indexes, divider):
WORKAROUND_CAST_TEMPLATE = """
detail::workaround_cast<T, decltype({arg})>({arg})
"""
lines = []
div = ''
tokens = [x.strip() for x in indexes.split(',')]
casts = [WORKAROUND_CAST_TEMPLATE.strip().format(arg=tok)
for tok in tokens]
for i in range(0, len(casts)):
if i%WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE==0:
div = ''
lines.append('')
lines[-1] += div + casts[i]
div = ','
return divider.join(lines)
def calc_indexes_count(indexes):
tokens = [x.strip() for x in indexes.split(',')]
return len(tokens)
class EmptyLinePrinter:
def print_once(self):
if not self.printed:
print("")
self.printed = True
printed = False
indexes = " a"
print(PROLOGUE)
funcs_count = 200 if len(sys.argv) == 1 else int(sys.argv[1])
max_args_on_a_line = len(ascii_letters)
for i in range(1, funcs_count):
if i % max_args_on_a_line == 0:
indexes += ",\n "
else:
indexes += ","
if i >= max_args_on_a_line:
indexes += ascii_letters[i // max_args_on_a_line - 1]
indexes += ascii_letters[i % max_args_on_a_line]
printed_casts = fold_workaround_cast(indexes.strip(), ",\n ")
indexes_count = calc_indexes_count(indexes.strip())
empty_printer = EmptyLinePrinter()
print("template <class T>")
print("constexpr auto tie_as_tuple(T& val, size_t_<" + str(i + 1) + ">) noexcept {")
if i < max_args_on_a_line:
print(" auto& [" + indexes.strip() + "] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
else:
print(" auto& [")
print(indexes)
print(" ] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
empty_printer.print_once()
if indexes_count < WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE:
print(" return ::boost::pfr::detail::make_tuple_of_references(" + printed_casts + ");")
else:
empty_printer.print_once()
print(" return ::boost::pfr::detail::make_tuple_of_references(")
print(" " + printed_casts)
print(" );")
print("}\n")
print(EPILOGUE)
|