95 lines
3.3 KiB
C++
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
|