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