mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-30 20:12:23 +00:00
Compare commits
15 Commits
reflection
...
member_to_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4328226b02 | ||
|
|
5d30e2d14b | ||
|
|
4f285bc9d4 | ||
|
|
f20f0b0b79 | ||
|
|
e360f0700d | ||
|
|
9cb98e103a | ||
|
|
c951f22eb7 | ||
|
|
93d02b86ce | ||
|
|
361b8e7d02 | ||
|
|
d96e25e829 | ||
|
|
e6bc1dd9f2 | ||
|
|
24cd193eee | ||
|
|
5f2aca762c | ||
|
|
18e010f989 | ||
|
|
8383f5e204 |
@@ -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>
|
||||
|
||||
@@ -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&&>{}
|
||||
);
|
||||
|
||||
85
include/boost/pfr/index_of.hpp
Normal file
85
include/boost/pfr/index_of.hpp
Normal 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
|
||||
49
include/boost/pfr/is_constexpr_default_constructible.hpp
Normal file
49
include/boost/pfr/is_constexpr_default_constructible.hpp
Normal 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
|
||||
41
test/core/run/is_constexpr_constructible.cpp
Normal file
41
test/core/run/is_constexpr_constructible.cpp
Normal 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>, "");
|
||||
}
|
||||
58
test/core/run/member_to_index.cpp
Normal file
58
test/core/run/member_to_index.cpp
Normal 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>{}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user