Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/boost/pfr/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ using tuple_element = detail::sequence_tuple::tuple_element<I, decltype( ::boost
template <std::size_t I, class T>
using tuple_element_t = typename tuple_element<I, T>::type;

template <auto ptr>
requires std::is_member_object_pointer_v<decltype(ptr)>
constexpr auto index = detail::index_impl<decltype(detail::class_of(ptr)), ptr>::value;

/// \brief Creates a `std::tuple` from fields of an \aggregate `val`.
///
Expand Down
56 changes: 56 additions & 0 deletions include/boost/pfr/detail/core_index.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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 <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/for_each_field_impl.hpp>

#include <type_traits>

namespace boost {
namespace pfr {
namespace detail {
template <typename T, typename TMember>
auto class_of(TMember T::*) -> T;

template <typename T, auto ptr, std::size_t index>
constexpr auto index_fn();

template <class T, auto ptr, std::size_t index = 0, bool out_of_bound = index >= tuple_size_v<T>>
requires std::is_member_object_pointer_v<decltype(ptr)>
struct index_impl {};

template <class T, auto ptr, std::size_t index>
requires std::is_member_object_pointer_v<decltype(ptr)>
struct index_impl<T, ptr, index, false> : decltype(index_fn<T, ptr, index>()) {};

template <typename T, auto ptr, std::size_t index>
constexpr auto index_fn() {
if constexpr (index < tuple_size_v<T>) {
using Class = decltype(class_of(ptr));
constexpr auto pfr_address = std::addressof(boost::pfr::get<index>(fake_object<Class>));
constexpr auto mem_address = std::addressof(fake_object<Class>.*ptr);

if constexpr (std::is_same_v<decltype(pfr_address), decltype(mem_address)>) {
if constexpr (pfr_address == mem_address) {
return std::integral_constant<std::size_t, index>{};
} else {
return index_impl<T, ptr, index + 1>{};
}
} else {
return index_impl<T, ptr, index + 1>{};
}
} else {
return index_impl<T, ptr, index + 1>{};
}
}
} // namespace pfr
} // namespace boost

#endif // BOOST_PFR_DETAIL_CORE_INDEX_HPP