2
0
mirror of https://github.com/boostorg/pfr.git synced 2026-01-19 04:22:13 +00:00
This commit is contained in:
Antony Polukhin
2026-01-12 20:32:43 +03:00
parent 9cb98e103a
commit e360f0700d
4 changed files with 81 additions and 33 deletions

View File

@@ -14,6 +14,7 @@
#include <boost/pfr/core_name.hpp>
#include <boost/pfr/functions_for.hpp>
#include <boost/pfr/functors.hpp>
#include <boost/pfr/index_of.hpp>
#include <boost/pfr/io.hpp>
#include <boost/pfr/io_fields.hpp>
#include <boost/pfr/ops.hpp>

View File

@@ -18,11 +18,9 @@
#include <boost/pfr/detail/for_each_field.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/tie_from_structure_tuple.hpp>
#include <boost/pfr/detail/fake_object.hpp>
#include <boost/pfr/tuple_size.hpp>
#if !defined(BOOST_PFR_INTERFACE_UNIT)
#include <type_traits>
#include <utility> // metaprogramming stuff
@@ -279,32 +277,6 @@ constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Eleme
return detail::tie_from_structure_tuple<Elements...>(args...);
}
template <typename M>
struct visitor {
template <class T>
constexpr void operator()(const T&, std::size_t) {}
constexpr void operator()(const M& field, std::size_t idx) {
const void* field_address = std::addressof(field);
if (target_address == field_address) {
result = idx;
}
}
const void* target_address;
std::size_t result;
};
template <typename T, typename M>
constexpr std::size_t index_of(M T::*mem_ptr) {
constexpr const T& value = boost::pfr::detail::fake_object<T>();
visitor<M> visit{std::addressof(value.*mem_ptr), boost::pfr::tuple_size_v<T>};
boost::pfr::for_each_field(value, visit);
return visit.result;
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr

View File

@@ -0,0 +1,72 @@
// Copyright (c) 2025-2026 Antony Polukhin
//
// 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_INDEX_OF_HPP
#define BOOST_PFR_INDEX_OF_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
#include <boost/pfr/detail/fake_object.hpp>
#include <boost/pfr/detail/for_each_field.hpp>
#if !defined(BOOST_PFR_INTERFACE_UNIT)
#include <type_traits>
#include <utility> // metaprogramming stuff
#endif
/// \file boost/pfr/index_of.hpp
/// \copybrief boost::pfr::index_of
namespace boost { namespace pfr {
namespace detail {
template <typename M>
struct address_comparing_visitor {
template <class T>
constexpr void operator()(const T&, std::size_t) noexcept {}
constexpr void operator()(const M& field, std::size_t idx) noexcept {
const void* field_address = std::addressof(field);
if (target_address == field_address) {
result = idx;
}
}
const void* const target_address;
std::size_t result;
};
}
BOOST_PFR_BEGIN_MODULE_EXPORT
template <typename T, typename M>
constexpr std::size_t index_of(M T::*mem_ptr) noexcept {
if (mem_ptr == nullptr) {
return ~static_cast<std::size_t>(0);
}
constexpr const T& value = boost::pfr::detail::fake_object<T>();
detail::address_comparing_visitor<M> visitor{
std::addressof(value.*mem_ptr),
~static_cast<std::size_t>(0)
};
::boost::pfr::detail::for_each_field(value, visitor);
return visitor.result;
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
#endif // BOOST_PFR_INDEX_OF_HPP

View File

@@ -3,9 +3,9 @@
// 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)
#include <boost/pfr/core.hpp>
#include <boost/pfr/index_of.hpp>
#include <cassert>
#include <limits>
#include <string>
#include <vector>
@@ -21,8 +21,11 @@ int main() {
static_assert(boost::pfr::index_of(&Sample::y) == 1);
static_assert(boost::pfr::index_of(&Sample::z) == 2);
#else
assert(boost::pfr::index_of(&Sample::x) == 0);
assert(boost::pfr::index_of(&Sample::y) == 1);
assert(boost::pfr::index_of(&Sample::z) == 2);
if (boost::pfr::index_of(&Sample::x) != 0) return 1;
if (boost::pfr::index_of(&Sample::y) != 1) return 2;
if (boost::pfr::index_of(&Sample::z) != 2) return 3;
#endif
decltype(&Sample::x) mem_ptr = nullptr;
if (boost::pfr::index_of(mem_ptr) != (std::numeric_limits<std::size_t>::max)()) return 4;
}