Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-08 08:57:47

0001 // Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 
0007 // Initial implementation by Bela Schaum, https://github.com/schaumb
0008 // The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
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         // We use std::min here to make the compiler diagnostic shorter and
0042         // cleaner in case of misconfigured BOOST_PFR_CORE_NAME_PARSING
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 // it might be compilation failed without this workaround sometimes
0081 // See https://github.com/llvm/llvm-project/issues/41751 for details
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     // Some of the following compiler specific macro may be defined only
0091     // inside the function body:
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 // clang 16 and earlier don't support address of non-static member as template parameter
0141 // but fortunately it's possible to use C++20 non-type template parameters in another way
0142 // even in clang 16 and more older clangs
0143 // all we need is to wrap pointer into 'clang_wrapper_t' and then pass it into template
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     // It's everything OK with address of non-static member as template parameter support on this compiler
0161     // so we don't need a wrapper here, just pass the pointer into template
0162     return arg;
0163 }
0164 
0165 #endif
0166 
0167 template <class MsvcWorkaround, auto ptr>
0168 consteval auto name_of_field() noexcept {
0169     // Sanity check: known field name must match the deduced one
0170     static_assert(
0171         sizeof(MsvcWorkaround)  // do not trigger if `name_of_field()` is not used
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 // Storing part of a string literal into an array minimizes the binary size.
0189 //
0190 // Without passing 'T' into 'name_of_field' different fields from different structures might have the same name!
0191 // See https://developercommunity.visualstudio.com/t/__FUNCSIG__-outputs-wrong-value-with-C/10458554 for details
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 }}} // namespace boost::pfr::detail
0261 
0262 #endif // BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
0263