From 80fd795622c40d613e439f8022f781bd5d616b18 Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Mon, 12 Aug 2024 13:52:11 +0000 Subject: [PATCH 1/2] Add `index` variable template to get index of member pointer --- include/boost/pfr/core.hpp | 4 +++ include/boost/pfr/detail/core_index.hpp | 46 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 include/boost/pfr/detail/core_index.hpp diff --git a/include/boost/pfr/core.hpp b/include/boost/pfr/core.hpp index 5a8e1dfd..46097aa1 100644 --- a/include/boost/pfr/core.hpp +++ b/include/boost/pfr/core.hpp @@ -129,6 +129,10 @@ using tuple_element = detail::sequence_tuple::tuple_element using tuple_element_t = typename tuple_element::type; +template + requires std::is_member_object_pointer_v +constexpr auto index = ::boost::detail::index_impl(::boost::pfr::detail::fake_object); /// \brief Creates a `std::tuple` from fields of an \aggregate `val`. /// diff --git a/include/boost/pfr/detail/core_index.hpp b/include/boost/pfr/detail/core_index.hpp new file mode 100644 index 00000000..d6432fe3 --- /dev/null +++ b/include/boost/pfr/detail/core_index.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2024 Uy Ha +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_PFR_DETAIL_CORE_INDEX_HPP +#define BOOST_PFR_DETAIL_CORE_INDEX_HPP +#pragma once + +#include + +#include + +#include + +namespace boost { +namespace pfr { +namespace detail { +template +auto class_of(TMember T::*) -> T; + +template +constexpr auto index_impl(T const &val) { + auto found = false; + auto result = 0; + + for_each_field( + val, [&](auto &&member, std::integral_constant) { + if (std::addressof(member) == std::addressof(val.*ptr)) { + found = true; + result = index; + } + }); + + if (!found) { + // What to do here? + } + + return result; +} +} +} // namespace pfr +} // namespace boost + +#endif // BOOST_PFR_DETAIL_CORE_INDEX_HPP From c23680a7c87d893eb74f5fcf969552889686157e Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Mon, 12 Aug 2024 19:13:22 +0000 Subject: [PATCH 2/2] Fix compilation error when a struct has members of different types --- include/boost/pfr/core.hpp | 3 +- include/boost/pfr/detail/core_index.hpp | 52 +++++++++++++++---------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/include/boost/pfr/core.hpp b/include/boost/pfr/core.hpp index 46097aa1..2ec5aa09 100644 --- a/include/boost/pfr/core.hpp +++ b/include/boost/pfr/core.hpp @@ -131,8 +131,7 @@ using tuple_element_t = typename tuple_element::type; template requires std::is_member_object_pointer_v -constexpr auto index = ::boost::detail::index_impl(::boost::pfr::detail::fake_object); +constexpr auto index = detail::index_impl::value; /// \brief Creates a `std::tuple` from fields of an \aggregate `val`. /// diff --git a/include/boost/pfr/detail/core_index.hpp b/include/boost/pfr/detail/core_index.hpp index d6432fe3..5039258b 100644 --- a/include/boost/pfr/detail/core_index.hpp +++ b/include/boost/pfr/detail/core_index.hpp @@ -9,36 +9,46 @@ #pragma once #include - #include -#include +#include namespace boost { namespace pfr { namespace detail { -template +template auto class_of(TMember T::*) -> T; -template -constexpr auto index_impl(T const &val) { - auto found = false; - auto result = 0; - - for_each_field( - val, [&](auto &&member, std::integral_constant) { - if (std::addressof(member) == std::addressof(val.*ptr)) { - found = true; - result = index; - } - }); - - if (!found) { - // What to do here? +template +constexpr auto index_fn(); + +template = tuple_size_v> + requires std::is_member_object_pointer_v +struct index_impl {}; + +template + requires std::is_member_object_pointer_v +struct index_impl : decltype(index_fn()) {}; + +template +constexpr auto index_fn() { + if constexpr (index < tuple_size_v) { + using Class = decltype(class_of(ptr)); + constexpr auto pfr_address = std::addressof(boost::pfr::get(fake_object)); + constexpr auto mem_address = std::addressof(fake_object.*ptr); + + if constexpr (std::is_same_v) { + if constexpr (pfr_address == mem_address) { + return std::integral_constant{}; + } else { + return index_impl{}; + } + } else { + return index_impl{}; + } + } else { + return index_impl{}; } - - return result; -} } } // namespace pfr } // namespace boost