Files
Adminive/backend/service/include/adminive/adapters/boost_pfr.hpp
T
2026-08-07 09:25:55 +08:00

95 lines
3.3 KiB
C++

#pragma once
#include "adminive/adapter.hpp"
#include <boost/pfr.hpp>
#if __has_include(<boost/pfr/core_name.hpp>)
#include <boost/pfr/core_name.hpp>
#define ADMINIVE_BOOST_PFR_HAS_NAMES 1
#else
#define ADMINIVE_BOOST_PFR_HAS_NAMES 0
#endif
#include <cstddef>
#include <string_view>
#include <type_traits>
namespace adminive {
template <class T>
struct Boost_Pfr_Name_Adapter;
namespace detail {
template <class T, std::size_t Index>
constexpr std::string_view pfr_name() noexcept {
#if ADMINIVE_BOOST_PFR_HAS_NAMES
return boost::pfr::get_name<Index, T>();
#else
return Boost_Pfr_Name_Adapter<T>::template name<Index>();
#endif
}
template <std::size_t Index, class Derived, class Base, class... Bases>
decltype(auto) pfr_base_get(Derived& value) noexcept {
constexpr std::size_t count = boost::pfr::tuple_size_v<Base>;
if constexpr(Index < count) {
return boost::pfr::get<Index>(static_cast<Base&>(value));
} else {
static_assert(sizeof...(Bases) != 0);
return pfr_base_get<Index - count, Derived, Bases...>(value);
}
}
template <std::size_t Index, class Derived, class Base, class... Bases>
decltype(auto) pfr_base_get(const Derived& value) noexcept {
constexpr std::size_t count = boost::pfr::tuple_size_v<Base>;
if constexpr(Index < count) {
return boost::pfr::get<Index>(static_cast<const Base&>(value));
} else {
static_assert(sizeof...(Bases) != 0);
return pfr_base_get<Index - count, Derived, Bases...>(value);
}
}
template <std::size_t Index, class Base, class... Bases>
constexpr std::string_view pfr_base_name() noexcept {
constexpr std::size_t count = boost::pfr::tuple_size_v<Base>;
if constexpr(Index < count) {
return pfr_name<Base, Index>();
} else {
static_assert(sizeof...(Bases) != 0);
return pfr_base_name<Index - count, Bases...>();
}
}
}
template <class T>
struct Boost_Pfr_Reflection_Adapter {
static constexpr std::size_t field_count = boost::pfr::tuple_size_v<T>;
template <std::size_t Index>
static decltype(auto) get(T& value) noexcept {
return boost::pfr::get<Index>(value);
}
template <std::size_t Index>
static decltype(auto) get(const T& value) noexcept {
return boost::pfr::get<Index>(value);
}
template <std::size_t Index>
static constexpr std::string_view name() noexcept {
return detail::pfr_name<T, Index>();
}
};
template <class Derived, class... Bases>
struct Boost_Pfr_Base_Reflection_Adapter {
static_assert(sizeof...(Bases) != 0);
static_assert((std::is_base_of_v<Bases, Derived> && ...));
static constexpr std::size_t field_count = (boost::pfr::tuple_size_v<Bases> + ... + 0);
template <std::size_t Index>
static decltype(auto) get(Derived& value) noexcept {
static_assert(Index < field_count);
return detail::pfr_base_get<Index, Derived, Bases...>(value);
}
template <std::size_t Index>
static decltype(auto) get(const Derived& value) noexcept {
static_assert(Index < field_count);
return detail::pfr_base_get<Index, Derived, Bases...>(value);
}
template <std::size_t Index>
static constexpr std::string_view name() noexcept {
static_assert(Index < field_count);
return detail::pfr_base_name<Index, Bases...>();
}
};
}
#undef ADMINIVE_BOOST_PFR_HAS_NAMES