Skip to content

Commit

Permalink
Make for_each_field() constexpr for c++17
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkaratarakis committed Jul 13, 2023
1 parent 2fa9036 commit 73b9af4
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/boost/pfr/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&
/// assert(sum == 42);
/// \endcode
template <class T, class F>
void for_each_field(T&& value, F&& func) {
constexpr void for_each_field(T&& value, F&& func) {
constexpr std::size_t fields_count_val = boost::pfr::detail::fields_count<std::remove_reference_t<T>>();

::boost::pfr::detail::for_each_field_dispatcher(
Expand Down
2 changes: 1 addition & 1 deletion include/boost/pfr/detail/core17.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ constexpr auto tie_as_tuple(T& val) noexcept {
}

template <class T, class F, std::size_t... I>
void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
constexpr void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
Expand Down
12 changes: 6 additions & 6 deletions include/boost/pfr/detail/for_each_field_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ template <std::size_t Index>
using size_t_ = std::integral_constant<std::size_t, Index >;

template <class T, class F, class I, class = decltype(std::declval<F>()(std::declval<T>(), I{}))>
void for_each_field_impl_apply(T&& v, F&& f, I i, long) {
constexpr void for_each_field_impl_apply(T&& v, F&& f, I i, long) {
std::forward<F>(f)(std::forward<T>(v), i);
}

template <class T, class F, class I>
void for_each_field_impl_apply(T&& v, F&& f, I /*i*/, int) {
constexpr void for_each_field_impl_apply(T&& v, F&& f, I /*i*/, int) {
std::forward<F>(f)(std::forward<T>(v));
}

#if !defined(__cpp_fold_expressions) || __cpp_fold_expressions < 201603
template <class T, class F, std::size_t... I>
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
const int v[] = {0, (
detail::for_each_field_impl_apply(sequence_tuple::get<I>(t), std::forward<F>(f), size_t_<I>{}, 1L),
0
Expand All @@ -41,7 +41,7 @@ void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type


template <class T, class F, std::size_t... I>
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
const int v[] = {0, (
detail::for_each_field_impl_apply(sequence_tuple::get<I>(std::move(t)), std::forward<F>(f), size_t_<I>{}, 1L),
0
Expand All @@ -50,12 +50,12 @@ void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type
}
#else
template <class T, class F, std::size_t... I>
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(t), std::forward<F>(f), size_t_<I>{}, 1L), ...);
}

template <class T, class F, std::size_t... I>
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(std::move(t)), std::forward<F>(f), size_t_<I>{}, 1L), ...);
}
#endif
Expand Down
11 changes: 11 additions & 0 deletions test/core/run/for_each_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ struct simple {

struct empty{};

#if BOOST_PFR_USE_CPP17
constexpr std::size_t get_field_count_through_for_each_field()
{
std::size_t counter = 0;
boost::pfr::for_each_field(simple{}, [&counter](auto&& /*val*/, std::size_t /*i*/) {
++ counter;
});
return counter;
}
static_assert(3 == get_field_count_through_for_each_field());
#endif

int main () {
std::size_t control = 0;
Expand Down

0 comments on commit 73b9af4

Please sign in to comment.