mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
Add function for_each_field_with_name (#171)
This commit is contained in:
@@ -230,6 +230,9 @@ Boost.PFR is a header only library that does not depend on Boost. You can just c
|
||||
|
||||
[funcref boost::pfr::io]
|
||||
]
|
||||
][
|
||||
[ [pfr_quick_examples_for_each_with_name] ]
|
||||
[ [funcref boost::pfr::for_each_field_with_name] ]
|
||||
][
|
||||
[ [pfr_quick_examples_functions_for] ]
|
||||
[ [macroref BOOST_PFR_FUNCTIONS_FOR] ]
|
||||
|
||||
@@ -77,6 +77,35 @@ void test_examples() {
|
||||
}
|
||||
|
||||
|
||||
// Disabling for MSVC as it gives a hard error on using local types:
|
||||
//
|
||||
// error C7631:
|
||||
// 'boost::pfr::detail::do_not_use_PFR_with_local_types<test_examples::sample>':
|
||||
// variable with internal linkage declared but not defined
|
||||
#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17 && !defined(_MSC_VER)
|
||||
{
|
||||
//[pfr_quick_examples_for_each_with_name
|
||||
// Print the name and value
|
||||
// of each element of the structure
|
||||
|
||||
struct test {
|
||||
int n;
|
||||
std::string str;
|
||||
};
|
||||
|
||||
test var{42, "Hello, World!"};
|
||||
|
||||
// Outputs:
|
||||
// n: 42
|
||||
// str: Hello, World!
|
||||
boost::pfr::for_each_field_with_name(var,
|
||||
[](std::string_view name, const auto& value) {
|
||||
std::cout << name << ": " << value << std::endl;
|
||||
});
|
||||
//]
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
//[pfr_quick_examples_tuple_size
|
||||
// Getting fields count of some structure
|
||||
|
||||
@@ -84,9 +84,30 @@ names_as_array() noexcept {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// Calls `func` for each field with its name of a `value`
|
||||
///
|
||||
/// \param func must have one of the following signatures:
|
||||
/// * any_return_type func(std::string_view name, U&& field) // field of value is perfect forwarded to function
|
||||
/// * any_return_type func(std::string_view name, U&& field, std::size_t i)
|
||||
/// * any_return_type func(std::string_view name, U&& value, I i) // Here I is an `std::integral_constant<size_t, field_index>`
|
||||
///
|
||||
/// \param value To each field of this variable will be the `func` applied.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct Toto { int a; char c; };
|
||||
/// Toto t {5, 'c'};
|
||||
/// auto print = [](std::string_view name, const auto& value){ std::cout << "Name: " << name << " Value: " << value << std::endl; };
|
||||
/// for_each_field_with_name(t, print);
|
||||
/// \endcode
|
||||
template <class T, class F>
|
||||
constexpr void for_each_field_with_name(T&& value, F&& func) {
|
||||
return boost::pfr::detail::for_each_field_with_name(std::forward<T>(value), std::forward<F>(func));
|
||||
}
|
||||
|
||||
BOOST_PFR_END_MODULE_EXPORT
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_CORE_NAME_HPP
|
||||
|
||||
|
||||
@@ -37,6 +37,15 @@ constexpr auto tie_as_names_tuple() noexcept {
|
||||
return detail::sequence_tuple::make_sequence_tuple();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class F>
|
||||
constexpr void for_each_field_with_name(T&& value, F&& func) {
|
||||
static_assert(
|
||||
sizeof(T) && false,
|
||||
"====================> Boost.PFR: Field's names extracting functionality requires C++20."
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/core.hpp>
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
#include <boost/pfr/detail/core.hpp>
|
||||
#include <boost/pfr/detail/sequence_tuple.hpp>
|
||||
@@ -241,6 +242,22 @@ constexpr auto tie_as_names_tuple() noexcept {
|
||||
return detail::tie_as_names_tuple_impl<T>(detail::make_index_sequence<detail::fields_count<T>()>{});
|
||||
}
|
||||
|
||||
template <class T, class F>
|
||||
constexpr void for_each_field_with_name(T&& value, F&& func) {
|
||||
return boost::pfr::for_each_field(
|
||||
std::forward<T>(value),
|
||||
[f = std::forward<F>(func)](auto&& field, auto index) mutable {
|
||||
using IndexType = decltype(index);
|
||||
using FieldType = decltype(field);
|
||||
constexpr auto name = boost::pfr::detail::get_name<std::remove_reference_t<T>, IndexType::value>();
|
||||
if constexpr (std::is_invocable_v<F, std::string_view, FieldType, IndexType>) {
|
||||
f(name, std::forward<FieldType>(field), index);
|
||||
} else {
|
||||
f(name, std::forward<FieldType>(field));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
|
||||
|
||||
31
test/core_name/run/for_each_field_with_name.cpp
Normal file
31
test/core_name/run/for_each_field_with_name.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2016-2024 Lena Bertho
|
||||
//
|
||||
// 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 <map>
|
||||
#include <string>
|
||||
|
||||
#include <boost/pfr/core_name.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
|
||||
struct SimpleStruct {
|
||||
char c;
|
||||
std::string str;
|
||||
};
|
||||
|
||||
|
||||
int main () {
|
||||
std::map<std::string, std::string> m;
|
||||
auto fill = [&m](std::string_view name, const auto& value){
|
||||
m[std::string(name)] = value;
|
||||
};
|
||||
|
||||
boost::pfr::for_each_field_with_name(SimpleStruct{ 'e', "test"}, fill);
|
||||
BOOST_TEST_EQ(m.size(), 2);
|
||||
BOOST_TEST_EQ(m["c"], "e");
|
||||
BOOST_TEST_EQ(m["str"], "test");
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user