2
0
mirror of https://github.com/boostorg/pfr.git synced 2026-01-30 20:12:23 +00:00

Compare commits

...

15 Commits

Author SHA1 Message Date
Antony Polukhin
4328226b02 fix 2026-01-22 12:34:49 +03:00
Antony Polukhin
5d30e2d14b wip 2026-01-22 12:22:45 +03:00
Antony Polukhin
4f285bc9d4 wip 2026-01-15 19:21:32 +03:00
Antony Polukhin
f20f0b0b79 provide a portable version 2026-01-12 20:38:51 +03:00
Antony Polukhin
e360f0700d cleanup 2026-01-12 20:32:43 +03:00
Antony Polukhin
9cb98e103a Update member_to_index.cpp 2026-01-06 21:10:24 +03:00
Antony Polukhin
c951f22eb7 Update member_to_index.cpp 2026-01-06 21:10:06 +03:00
Antony Polukhin
93d02b86ce Update for_each_field.hpp 2026-01-06 20:43:12 +03:00
Antony Polukhin
361b8e7d02 Update core.hpp 2026-01-06 20:01:16 +03:00
Antony Polukhin
d96e25e829 Update core.hpp 2026-01-06 19:38:42 +03:00
Antony Polukhin
e6bc1dd9f2 Update core.hpp 2026-01-06 19:17:42 +03:00
Antony Polukhin
24cd193eee Update core.hpp 2026-01-06 19:15:12 +03:00
Antony Polukhin
5f2aca762c github editor is a piece of bad software 2026-01-06 19:06:12 +03:00
Antony Polukhin
18e010f989 cleanup 2026-01-05 23:27:14 +03:00
Antony Polukhin
8383f5e204 Member pointer to index (WIP) 2026-01-05 23:18:42 +03:00
6 changed files with 237 additions and 2 deletions

View File

@@ -14,8 +14,10 @@
#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/is_constexpr_default_constructible.hpp>
#include <boost/pfr/ops.hpp>
#include <boost/pfr/ops_fields.hpp>
#include <boost/pfr/tuple_size.hpp>

View File

@@ -42,14 +42,14 @@ constexpr void for_each_field(T&& value, F&& func) {
::boost::pfr::detail::for_each_field_dispatcher(
value,
[f = std::forward<F>(func)](auto&& t) mutable {
[&func](auto&& t) mutable {
// MSVC related workaround. Its lambdas do not capture constexprs.
constexpr std::size_t fields_count_val_in_lambda
= boost::pfr::detail::fields_count<std::remove_reference_t<T>>();
::boost::pfr::detail::for_each_field_impl(
t,
std::forward<F>(f),
std::forward<F>(func),
detail::make_index_sequence<fields_count_val_in_lambda>{},
std::is_rvalue_reference<T&&>{}
);

View File

@@ -0,0 +1,85 @@
// 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/for_each_field.hpp>
#include <boost/pfr/is_constexpr_default_constructible.hpp>
#if !defined(BOOST_PFR_INTERFACE_UNIT)
#include <type_traits>
#include <memory> // std::addressof
#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, const T& value) noexcept {
if (mem_ptr == nullptr) {
return ~static_cast<std::size_t>(0);
}
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;
}
template <typename T, typename M>
constexpr std::size_t index_of(M T::*mem_ptr) noexcept {
static_assert(
boost::pfr::is_constexpr_default_constructible_v<T>,
"====================> Boost.PFR: T should be default constructible in constant evaluations. "
"Either add `constexpr` to constructors of member types or use the boost::pfr::index_of() overload "
"with explicit `const T& value` parameter."
);
// boost::pfr::is_constexpr_default_constructible_v<T> gives a faint hope that the
// compiler would be able to optimize away the temporary `T{}`.
return ::boost::pfr::index_of(mem_ptr, T{});
}
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

@@ -0,0 +1,49 @@
// 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_IS_CONSTEXPR_DEFAULT_CONSTRUCTIBLE_HPP
#define BOOST_PFR_IS_CONSTEXPR_DEFAULT_CONSTRUCTIBLE_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
#if !defined(BOOST_PFR_INTERFACE_UNIT)
#include <type_traits>
#endif
namespace boost { namespace pfr {
namespace detail {
template <class T, int = (static_cast<void>(T{}), 0)>
constexpr std::true_type is_constexpr_default_constructible(long) noexcept {
return {};
}
template <class T>
constexpr std::false_type is_constexpr_default_constructible(int) noexcept {
return {};
}
} // namespace detail
BOOST_PFR_BEGIN_MODULE_EXPORT
template <class T>
struct is_constexpr_default_constructible
: decltype(detail::is_constexpr_default_constructible<T>(1L))
{};
template <class T>
constexpr bool is_constexpr_default_constructible_v
= decltype(detail::is_constexpr_default_constructible<T>(1L))::value;
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
#endif // BOOST_PFR_IS_CONSTEXPR_DEFAULT_CONSTRUCTIBLE_HPP

View File

@@ -0,0 +1,41 @@
// 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)
#include <boost/pfr/is_constexpr_default_constructible.hpp>
#include <string>
struct Yes {
int a;
double b;
char c;
};
struct Yes2 {
int a;
double b;
char c;
Yes d[42];
};
class MyClass{
public:
MyClass();
~MyClass();
};
struct No {
int a;
double b;
char c;
std::string str;
MyClass mc;
};
int main() {
static_assert(is_constexpr_default_constructible_v<Yes>, "");
static_assert(is_constexpr_default_constructible_v<Yes2>, "");
static_assert(!is_constexpr_default_constructible_v<No>, "");
}

View File

@@ -0,0 +1,58 @@
// 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)
#include <boost/pfr/index_of.hpp>
#include <limits>
#include <string>
#include <vector>
struct Sample {
std::string x;
std::vector<int> y;
std::string z;
};
struct TrivialSample {
int x;
short y;
bool z;
};
template <class T>
int test_if_constexpr_default_constructible(std::false_type) {
return 0;
}
template <class T>
int test_if_constexpr_default_constructible(std::true_type) {
if (boost::pfr::index_of(&T::x) != 0) return 31;
if (boost::pfr::index_of(&T::y) != 1) return 32;
if (boost::pfr::index_of(&T::z) != 2) return 33;
return 0;
}
int main() {
#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_CPP26
static_assert(boost::pfr::index_of(&TrivialSample::x) == 0);
static_assert(boost::pfr::index_of(&TrivialSample::y) == 1);
static_assert(boost::pfr::index_of(&TrivialSample::z) == 2);
#endif
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;
decltype(&Sample::x) mem_ptr = nullptr;
if (boost::pfr::index_of(mem_ptr, {}) != (std::numeric_limits<std::size_t>::max)()) return 4;
if (boost::pfr::index_of(&TrivialSample::x) != 0) return 11;
if (boost::pfr::index_of(&TrivialSample::y) != 1) return 12;
if (boost::pfr::index_of(&TrivialSample::z) != 2) return 13;
return test_if_constexpr_default_constructible<Sample>(
boost::pfr::is_constexpr_default_constructible<Sample>{}
);
}