Skip to content

Commit c7d1336

Browse files
update to Boost.PFR 1.75.0
1 parent 66ee6fb commit c7d1336

39 files changed

+1027
-1737
lines changed

include/boost/pfr.hpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
#define BOOST_PFR_HPP
88

99
/// \file boost/pfr.hpp
10-
/// Includes all the Boost.PFR headers, except \xmlonly<link linkend='header.boost.pfr.flat.global_ops_hpp'>boost/pfr/flat/global_ops.hpp</link>\endxmlonly and \xmlonly<link linkend='header.boost.pfr.precise.global_ops_hpp'>boost/pfr/precise/global_ops.hpp</link>\endxmlonly
10+
/// Includes all the Boost.PFR headers
1111

12-
#include <boost/pfr/precise.hpp>
13-
#include <boost/pfr/flat.hpp>
12+
#include <boost/pfr/core.hpp>
13+
#include <boost/pfr/functions_for.hpp>
14+
#include <boost/pfr/functors.hpp>
15+
#include <boost/pfr/io.hpp>
16+
#include <boost/pfr/io_fields.hpp>
17+
#include <boost/pfr/ops.hpp>
18+
#include <boost/pfr/ops_fields.hpp>
19+
#include <boost/pfr/tuple_size.hpp>
1420

1521
#endif // BOOST_PFR_HPP
16-

include/boost/pfr/precise/core.hpp renamed to include/boost/pfr/core.hpp

+85-36
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,33 @@
33
// Distributed under the Boost Software License, Version 1.0. (See accompanying
44
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
55

6-
#ifndef BOOST_PFR_PRECISE_CORE_HPP
7-
#define BOOST_PFR_PRECISE_CORE_HPP
6+
#ifndef BOOST_PFR_CORE_HPP
7+
#define BOOST_PFR_CORE_HPP
88
#pragma once
99

1010
#include <boost/pfr/detail/config.hpp>
1111

12-
#include <type_traits>
13-
#include <utility> // metaprogramming stuff
12+
#include <boost/pfr/detail/core.hpp>
1413

1514
#include <boost/pfr/detail/sequence_tuple.hpp>
1615
#include <boost/pfr/detail/stdtuple.hpp>
1716
#include <boost/pfr/detail/for_each_field_impl.hpp>
1817
#include <boost/pfr/detail/make_integer_sequence.hpp>
18+
#include <boost/pfr/detail/tie_from_structure_tuple.hpp>
1919

20-
#include <boost/pfr/precise/tuple_size.hpp>
21-
#if BOOST_PFR_USE_CPP17
22-
# include <boost/pfr/detail/core17.hpp>
23-
#else
24-
# include <boost/pfr/detail/core14.hpp>
25-
#endif
20+
#include <type_traits>
21+
#include <utility> // metaprogramming stuff
2622

27-
#include <boost/pfr/detail/tie_from_structure_tuple.hpp>
23+
#include <boost/pfr/tuple_size.hpp>
24+
25+
/// \file boost/pfr/core.hpp
26+
/// Contains all the basic tuple-like interfaces \forcedlink{get}, \forcedlink{tuple_size}, \forcedlink{tuple_element_t}, and others.
27+
///
28+
/// \b Synopsis:
2829

2930
namespace boost { namespace pfr {
3031

31-
/// \brief Returns reference or const reference to a field with index `I` in aggregate T.
32-
///
33-
/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}.
32+
/// \brief Returns reference or const reference to a field with index `I` in \aggregate `val`.
3433
///
3534
/// \b Example:
3635
/// \code
@@ -47,38 +46,52 @@ constexpr decltype(auto) get(const T& val) noexcept {
4746

4847
/// \overload get
4948
template <std::size_t I, class T>
50-
constexpr decltype(auto) get(T& val) noexcept {
49+
constexpr decltype(auto) get(T& val
50+
#if !BOOST_PFR_USE_CPP17
51+
, std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
52+
#endif
53+
) noexcept {
5154
return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
5255
}
5356

57+
#if !BOOST_PFR_USE_CPP17
58+
/// \overload get
59+
template <std::size_t I, class T>
60+
constexpr auto get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
61+
static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
62+
return 0;
63+
}
64+
#endif
5465

55-
/// \brief `tuple_element` has a `typedef type-of-a-field-with-index-I-in-aggregate-T type;`
56-
///
57-
/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}.
66+
67+
/// \overload get
68+
template <std::size_t I, class T>
69+
constexpr auto get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = 0) noexcept {
70+
return std::move(detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) ));
71+
}
72+
73+
74+
/// \brief `tuple_element` has a member typedef `type` that returns the type of a field with index I in \aggregate T.
5875
///
5976
/// \b Example:
6077
/// \code
61-
/// std::vector< boost::pfr::tuple_element<0, my_structure>::type > v;
78+
/// std::vector< boost::pfr::tuple_element<0, my_structure>::type > v;
6279
/// \endcode
6380
template <std::size_t I, class T>
6481
using tuple_element = detail::sequence_tuple::tuple_element<I, decltype( ::boost::pfr::detail::tie_as_tuple(std::declval<T&>()) ) >;
6582

6683

67-
/// \brief Type of a field with index `I` in aggregate `T`.
68-
///
69-
/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}.
84+
/// \brief Type of a field with index `I` in \aggregate `T`.
7085
///
7186
/// \b Example:
7287
/// \code
73-
/// std::vector< boost::pfr::tuple_element_t<0, my_structure> > v;
88+
/// std::vector< boost::pfr::tuple_element_t<0, my_structure> > v;
7489
/// \endcode
7590
template <std::size_t I, class T>
7691
using tuple_element_t = typename tuple_element<I, T>::type;
7792

7893

79-
/// \brief Creates an `std::tuple` from an aggregate T.
80-
///
81-
/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}.
94+
/// \brief Creates a `std::tuple` from fields of an \aggregate `val`.
8295
///
8396
/// \b Example:
8497
/// \code
@@ -96,33 +109,67 @@ constexpr auto structure_to_tuple(const T& val) noexcept {
96109
}
97110

98111

99-
/// \brief Creates an `std::tuple` with lvalue references to fields of an aggregate T.
112+
/// \brief std::tie` like function that ties fields of a structure.
100113
///
101-
/// \b Requires: C++17 or \flatpod{C++14 flat POD or C++14 with not disabled Loophole}.
114+
/// \returns a `std::tuple` with lvalue and const lvalue references to fields of an \aggregate `val`.
102115
///
103116
/// \b Example:
104117
/// \code
118+
/// void foo(const int&, const short&);
105119
/// struct my_struct { int i, short s; };
120+
///
121+
/// const my_struct const_s{1, 2};
122+
/// std::apply(foo, structure_tie(const_s));
123+
///
106124
/// my_struct s;
107125
/// structure_tie(s) = std::tuple<int, short>{10, 11};
108126
/// assert(s.s == 11);
109127
/// \endcode
110128
template <class T>
111-
constexpr auto structure_tie(T& val) noexcept {
129+
constexpr auto structure_tie(const T& val) noexcept {
130+
return detail::make_conststdtiedtuple_from_tietuple(
131+
detail::tie_as_tuple(const_cast<T&>(val)),
132+
detail::make_index_sequence< tuple_size_v<T> >()
133+
);
134+
}
135+
136+
137+
/// \overload structure_tie
138+
template <class T>
139+
constexpr auto structure_tie(T& val
140+
#if !BOOST_PFR_USE_CPP17
141+
, std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
142+
#endif
143+
) noexcept {
112144
return detail::make_stdtiedtuple_from_tietuple(
113145
detail::tie_as_tuple(val),
114146
detail::make_index_sequence< tuple_size_v<T> >()
115147
);
116148
}
117149

150+
#if !BOOST_PFR_USE_CPP17
151+
/// \overload structure_tie
152+
template <class T>
153+
constexpr auto structure_tie(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
154+
static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on non const non assignable type is allowed only in C++17");
155+
return 0;
156+
}
157+
#endif
158+
159+
160+
/// \overload structure_tie
161+
template <class T>
162+
constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = 0) noexcept {
163+
static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on rvalue references is forbidden");
164+
return 0;
165+
}
166+
118167
/// Calls `func` for each field of a `value`.
119168
///
120-
/// \b Requires: C++17 or \constexprinit{C++14 constexpr aggregate intializable type}.
121-
///
122169
/// \param func must have one of the following signatures:
123170
/// * any_return_type func(U&& field) // field of value is perfect forwarded to function
124171
/// * any_return_type func(U&& field, std::size_t i)
125-
/// * any_return_type func(U&& value, I i) // Here I is an `std::integral_constant<size_t, field_index>`
172+
/// * any_return_type func(U&& value, I i) // Here I is an `std::integral_constant<size_t, field_index>`
126173
///
127174
/// \param value To each field of this variable will be the `func` applied.
128175
///
@@ -140,7 +187,7 @@ void for_each_field(T&& value, F&& func) {
140187
::boost::pfr::detail::for_each_field_dispatcher(
141188
value,
142189
[f = std::forward<F>(func)](auto&& t) mutable {
143-
// MSVC related workaround. It's lambdas do not capture constexprs.
190+
// MSVC related workaround. Its lambdas do not capture constexprs.
144191
constexpr std::size_t fields_count_val_in_lambda
145192
= boost::pfr::detail::fields_count<std::remove_reference_t<T>>();
146193

@@ -155,8 +202,10 @@ void for_each_field(T&& value, F&& func) {
155202
);
156203
}
157204

158-
/// \brief Create a tuple of lvalue references capable of de-structuring
159-
/// assignment from fields of an aggregate T.
205+
/// \brief std::tie-like function that allows assigning to tied values from aggregates.
206+
///
207+
/// \returns an object with lvalue references to `args...`; on assignment of an \aggregate value to that
208+
/// object each field of an aggregate is assigned to the corresponding `args...` reference.
160209
///
161210
/// \b Example:
162211
/// \code
@@ -174,4 +223,4 @@ constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Eleme
174223

175224
}} // namespace boost::pfr
176225

177-
#endif // BOOST_PFR_PRECISE_CORE_HPP
226+
#endif // BOOST_PFR_CORE_HPP

include/boost/pfr/detail/config.hpp

+24-7
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,48 @@
77
#define BOOST_PFR_DETAIL_CONFIG_HPP
88
#pragma once
99

10+
#include <type_traits> // to get non standard platform macro definitions (__GLIBCXX__ for example)
11+
1012
// Reminder:
11-
// * MSVC++ 1?.? _MSC_VER > 1900 (Visual Studio 2017)
13+
// * MSVC++ 14.2 _MSC_VER == 1927 <- Loophole is known to work (Visual Studio ????)
14+
// * MSVC++ 14.1 _MSC_VER == 1916 <- Loophole is known to NOT work (Visual Studio 2017)
1215
// * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
1316
// * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
1417

1518
#if defined(_MSC_VER)
16-
# if _MSC_VER <= 1900
17-
# error Boost.PFR library requires MSVC with c++17 support (Visual Studio 2017 or later).
19+
# if !defined(_MSVC_LANG) || _MSC_VER <= 1900
20+
# error Boost.PFR library requires more modern MSVC compiler.
1821
# endif
1922
#elif __cplusplus < 201402L
2023
# error Boost.PFR library requires at least C++14.
2124
#endif
2225

2326
#ifndef BOOST_PFR_USE_LOOPHOLE
24-
# if !defined(__clang_major__) || __clang_major__ < 8
27+
# if defined(_MSC_VER)
28+
# if _MSC_VER >= 1927
29+
# define BOOST_PFR_USE_LOOPHOLE 1
30+
# else
31+
# define BOOST_PFR_USE_LOOPHOLE 0
32+
# endif
33+
# elif defined(__clang_major__) && __clang_major__ >= 8
34+
# define BOOST_PFR_USE_LOOPHOLE 0
35+
# else
2536
# define BOOST_PFR_USE_LOOPHOLE 1
2637
# endif
2738
#endif
2839

2940
#ifndef BOOST_PFR_USE_CPP17
3041
# ifdef __cpp_structured_bindings
3142
# define BOOST_PFR_USE_CPP17 1
32-
# elif defined(_MSC_VER)
33-
# warning PFR library supports MSVC compiler only with /std:c++latest or /std:c++17 flag. Assuming that you`ve used it. Define `BOOST_PFR_USE_CPP17` to 1 to suppress this warning.
34-
# define BOOST_PFR_USE_CPP17 1
43+
# elif defined(_MSVC_LANG)
44+
# if _MSVC_LANG >= 201703L
45+
# define BOOST_PFR_USE_CPP17 1
46+
# else
47+
# define BOOST_PFR_USE_CPP17 0
48+
# if !BOOST_PFR_USE_LOOPHOLE
49+
# error Boost.PFR requires /std:c++latest or /std:c++17 flags on your compiler.
50+
# endif
51+
# endif
3552
# else
3653
# define BOOST_PFR_USE_CPP17 0
3754
# endif

include/boost/pfr/detail/core.hpp

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2016-2020 Antony Polukhin
2+
//
3+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#ifndef BOOST_PFR_DETAIL_CORE_HPP
7+
#define BOOST_PFR_DETAIL_CORE_HPP
8+
#pragma once
9+
10+
#include <boost/pfr/detail/config.hpp>
11+
12+
// Each core provides `boost::pfr::detail::tie_as_tuple` and
13+
// `boost::pfr::detail::for_each_field_dispatcher` functions.
14+
//
15+
// The whole PFR library is build on top of those two functions.
16+
#if BOOST_PFR_USE_CPP17
17+
# include <boost/pfr/detail/core17.hpp>
18+
#elif BOOST_PFR_USE_LOOPHOLE
19+
# include <boost/pfr/detail/core14_loophole.hpp>
20+
#else
21+
# include <boost/pfr/detail/core14_classic.hpp>
22+
#endif
23+
24+
#endif // BOOST_PFR_DETAIL_CORE_HPP

include/boost/pfr/detail/core14.hpp

-18
This file was deleted.

include/boost/pfr/detail/core14_classic.hpp

+3-11
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ constexpr auto internal_tuple_with_same_alignment() noexcept {
508508

509509
static_assert(
510510
std::is_trivial<type>::value && std::is_standard_layout<type>::value,
511-
"====================> Boost.PFR: Type can not be used is flat_ functions, because it's not POD"
511+
"====================> Boost.PFR: Type can not be reflected without Loophole or C++17, because it's not POD"
512512
);
513513
static_assert(!std::is_reference<type>::value, "====================> Boost.PFR: Not applyable");
514514
constexpr auto res = detail::as_flat_tuple_impl<type>(
@@ -528,7 +528,7 @@ struct ubiq_is_flat_refelectable {
528528

529529
template <class Type>
530530
constexpr operator Type() const noexcept {
531-
is_flat_refelectable = std::is_fundamental<Type>::value;
531+
is_flat_refelectable = std::is_fundamental<std::remove_pointer_t<Type>>::value;
532532
return {};
533533
}
534534
};
@@ -562,8 +562,6 @@ auto tie_as_flat_tuple(T& lvalue) noexcept {
562562
return boost::pfr::detail::make_flat_tuple_of_references(lvalue, getter, size_t_<0>{}, size_t_<tuple_type::size_v>{});
563563
}
564564

565-
#if !BOOST_PFR_USE_CPP17
566-
567565
template <class T>
568566
auto tie_as_tuple(T& val) noexcept {
569567
static_assert(
@@ -572,13 +570,11 @@ auto tie_as_tuple(T& val) noexcept {
572570
);
573571
static_assert(
574572
boost::pfr::detail::is_flat_refelectable<T>( detail::make_index_sequence<boost::pfr::detail::fields_count<T>()>{} ),
575-
"====================> Boost.PFR: Not possible in C++14 to represent that type without loosing information. Use boost::pfr::flat_ version, or change type definition, or enable C++17"
573+
"====================> Boost.PFR: Not possible in C++14 to represent that type without loosing information. Change type definition or enable C++17"
576574
);
577575
return boost::pfr::detail::tie_as_flat_tuple(val);
578576
}
579577

580-
#endif // #if !BOOST_PFR_USE_CPP17
581-
582578
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
583579

584580
///////////////////// Structure that can be converted to copy of anything
@@ -597,8 +593,6 @@ struct ubiq_constructor_constexpr_copy {
597593

598594
/////////////////////
599595

600-
#if !BOOST_PFR_USE_CPP17
601-
602596
template <class T, std::size_t... I>
603597
struct is_constexpr_aggregate_initializable { // TODO: try to fix it
604598
template <T = T{ ubiq_constructor_constexpr_copy{I}... } >
@@ -697,8 +691,6 @@ void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
697691
);
698692
}
699693

700-
#endif // #if !BOOST_PFR_USE_CPP17
701-
702694
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
703695

704696

0 commit comments

Comments
 (0)