File indexing completed on 2025-01-18 09:43:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
0012 #define BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
0013 #pragma once
0014
0015 #include <boost/pfr/detail/config.hpp>
0016 #include <boost/pfr/detail/core.hpp>
0017 #include <boost/pfr/detail/sequence_tuple.hpp>
0018 #include <boost/pfr/detail/make_integer_sequence.hpp>
0019 #include <boost/pfr/detail/fields_count.hpp>
0020 #include <boost/pfr/detail/stdarray.hpp>
0021 #include <boost/pfr/detail/fake_object.hpp>
0022 #include <type_traits>
0023 #include <string_view>
0024 #include <array>
0025 #include <memory> // for std::addressof
0026
0027 namespace boost { namespace pfr { namespace detail {
0028
0029 struct core_name_skip {
0030 std::size_t size_at_begin;
0031 std::size_t size_at_end;
0032 bool is_backward;
0033 std::string_view until_runtime;
0034
0035 consteval std::string_view apply(std::string_view sv) const noexcept {
0036
0037
0038 sv.remove_prefix((std::min)(size_at_begin, sv.size()));
0039 sv.remove_suffix((std::min)(size_at_end, sv.size()));
0040 if (until_runtime.empty()) {
0041 return sv;
0042 }
0043
0044 const auto found = is_backward ? sv.rfind(until_runtime)
0045 : sv.find(until_runtime);
0046
0047 const auto cut_until = found + until_runtime.size();
0048 const auto safe_cut_until = (std::min)(cut_until, sv.size());
0049 return sv.substr(safe_cut_until);
0050 }
0051 };
0052
0053 struct backward {
0054 explicit consteval backward(std::string_view value) noexcept
0055 : value(value)
0056 {}
0057
0058 std::string_view value;
0059 };
0060
0061 consteval core_name_skip make_core_name_skip(std::size_t size_at_begin,
0062 std::size_t size_at_end,
0063 std::string_view until_runtime) noexcept
0064 {
0065 return core_name_skip{size_at_begin, size_at_end, false, until_runtime};
0066 }
0067
0068 consteval core_name_skip make_core_name_skip(std::size_t size_at_begin,
0069 std::size_t size_at_end,
0070 backward until_runtime) noexcept
0071 {
0072 return core_name_skip{size_at_begin, size_at_end, true, until_runtime.value};
0073 }
0074
0075
0076
0077 template <class>
0078 consteval std::string_view clang_workaround(std::string_view value) noexcept
0079 {
0080 return value;
0081 }
0082
0083 template <class MsvcWorkaround, auto ptr>
0084 consteval auto name_of_field_impl() noexcept {
0085
0086
0087
0088 #ifndef BOOST_PFR_FUNCTION_SIGNATURE
0089 # if defined(__FUNCSIG__)
0090 # define BOOST_PFR_FUNCTION_SIGNATURE __FUNCSIG__
0091 # elif defined(__PRETTY_FUNCTION__) || defined(__GNUC__) || defined(__clang__)
0092 # define BOOST_PFR_FUNCTION_SIGNATURE __PRETTY_FUNCTION__
0093 # else
0094 # define BOOST_PFR_FUNCTION_SIGNATURE ""
0095 # endif
0096 #endif
0097
0098 constexpr std::string_view sv = detail::clang_workaround<MsvcWorkaround>(BOOST_PFR_FUNCTION_SIGNATURE);
0099 static_assert(!sv.empty(),
0100 "====================> Boost.PFR: Field reflection parser configured in a wrong way. "
0101 "Please define the BOOST_PFR_FUNCTION_SIGNATURE to a compiler specific macro, "
0102 "that outputs the whole function signature including non-type template parameters."
0103 );
0104
0105 constexpr auto skip = detail::make_core_name_skip BOOST_PFR_CORE_NAME_PARSING;
0106 static_assert(skip.size_at_begin + skip.size_at_end + skip.until_runtime.size() < sv.size(),
0107 "====================> Boost.PFR: Field reflection parser configured in a wrong way. "
0108 "It attempts to skip more chars than available. "
0109 "Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
0110 "'Limitations and Configuration' for more information."
0111 );
0112 constexpr auto fn = skip.apply(sv);
0113 static_assert(
0114 !fn.empty(),
0115 "====================> Boost.PFR: Extraction of field name is misconfigured for your compiler. "
0116 "It skipped all the input, leaving the field name empty. "
0117 "Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
0118 "'Limitations and Configuration' for more information."
0119 );
0120 auto res = std::array<char, fn.size()+1>{};
0121
0122 auto* out = res.data();
0123 for (auto x: fn) {
0124 *out = x;
0125 ++out;
0126 }
0127
0128 return res;
0129 }
0130
0131 #ifdef __clang__
0132 #pragma clang diagnostic push
0133 #pragma clang diagnostic ignored "-Wundefined-var-template"
0134
0135
0136
0137
0138
0139 template <class T>
0140 struct clang_wrapper_t {
0141 T v;
0142 };
0143 template <class T>
0144 clang_wrapper_t(T) -> clang_wrapper_t<T>;
0145
0146 template <class T>
0147 constexpr auto make_clang_wrapper(const T& arg) noexcept {
0148 return clang_wrapper_t{arg};
0149 }
0150
0151 #else
0152
0153 template <class T>
0154 constexpr const T& make_clang_wrapper(const T& arg) noexcept {
0155
0156
0157 return arg;
0158 }
0159
0160 #endif
0161
0162 template <class MsvcWorkaround, auto ptr>
0163 consteval auto name_of_field() noexcept {
0164
0165 static_assert(
0166 sizeof(MsvcWorkaround)
0167 && std::string_view{
0168 detail::name_of_field_impl<
0169 core_name_skip, detail::make_clang_wrapper(std::addressof(
0170 detail::fake_object<core_name_skip>().size_at_begin
0171 ))
0172 >().data()
0173 } == "size_at_begin",
0174 "====================> Boost.PFR: Extraction of field name is misconfigured for your compiler. "
0175 "It does not return the proper field name. "
0176 "Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
0177 "'Limitations and Configuration' for more information."
0178 );
0179
0180 return detail::name_of_field_impl<MsvcWorkaround, ptr>();
0181 }
0182
0183
0184
0185
0186
0187 template <class T, std::size_t I>
0188 inline constexpr auto stored_name_of_field = detail::name_of_field<T,
0189 detail::make_clang_wrapper(std::addressof(detail::sequence_tuple::get<I>(
0190 detail::tie_as_tuple(detail::fake_object<T>())
0191 )))
0192 >();
0193
0194 #ifdef __clang__
0195 #pragma clang diagnostic pop
0196 #endif
0197
0198 template <class T, std::size_t... I>
0199 constexpr auto tie_as_names_tuple_impl(std::index_sequence<I...>) noexcept {
0200 return detail::sequence_tuple::make_sequence_tuple(std::string_view{stored_name_of_field<T, I>.data()}...);
0201 }
0202
0203 template <class T, std::size_t I>
0204 constexpr std::string_view get_name() noexcept {
0205 static_assert(
0206 !std::is_union<T>::value,
0207 "====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
0208 );
0209 static_assert(
0210 !std::is_array<T>::value,
0211 "====================> Boost.PFR: It is impossible to extract name from old C array since it doesn't have named members"
0212 );
0213 static_assert(
0214 sizeof(T) && BOOST_PFR_USE_CPP17,
0215 "====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
0216 );
0217
0218 return stored_name_of_field<T, I>.data();
0219 }
0220
0221 template <class T>
0222 constexpr auto tie_as_names_tuple() noexcept {
0223 static_assert(
0224 !std::is_union<T>::value,
0225 "====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
0226 );
0227 static_assert(
0228 !std::is_array<T>::value,
0229 "====================> Boost.PFR: It is impossible to extract name from old C array since it doesn't have named members"
0230 );
0231 static_assert(
0232 sizeof(T) && BOOST_PFR_USE_CPP17,
0233 "====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
0234 );
0235
0236 return detail::tie_as_names_tuple_impl<T>(detail::make_index_sequence<detail::fields_count<T>()>{});
0237 }
0238
0239 }}}
0240
0241 #endif
0242