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