2
0
mirror of https://github.com/boostorg/pfr.git synced 2026-01-22 05:22:32 +00:00

Compare commits

..

28 Commits

Author SHA1 Message Date
Antony Polukhin
f09e6aeae9 Fix clang-tidy warnings 2024-10-19 16:25:09 +03:00
Anarthal (Rubén Pérez)
69263f4757 Fix unused warning in fields_count.hpp (#187) 2024-10-15 09:41:21 +03:00
Antony Polukhin
469ac134f3 Micro-optimize PFR fields detection (#188)
* Start upper bound fields search from `4` fields, to avoid slow startup on typical workloads
* Inline the `fields_count_binary_search_unbounded` function to reduce template instantiations depth by 1
* Renamed `min` to `min_of_size_t` to avoid weired syntax
* Applied idea of better error reporting from #120
* Do not start fields count computation if one of the static asserts failed. That speedups error reporting in edge cases
* Use `std::*_t` versions of traits as they are faster in some implementations
* Rewrite binary search to simplify it and to avoid degradation to linear search on types that have constructor from variadic pack
* Remove default template parameters to simplify code

As a result, the whole test suite now runs 10%-25% faster on MSVC, ~20% faster on Clang, and 7%-20% faster on GCC.
2024-10-15 09:39:26 +03:00
Zachary Wassall
ff415a26ff Improve field count typical case performance (#120)
The tightest upper bound one can specify on the number of fields in a
struct is `sizeof(type) * CHAR_BIT`. So this was previously used when
performing a binary search for the field count. This upper bound is
extremely loose when considering a typical large struct, which is more
likely to contain a relatively small number of relatively large fields
rather than the other way around. The binary search range being multiple
orders of magnitude larger than necessary wouldn't have been a
significant issue if each test was cheap, but they're not. Testing a
field count of N costs O(N) memory and time. As a result, the initial
few steps of the binary search may be prohibitively expensive.

The primary optimization introduced by these changes is to use unbounded
binary search, a.k.a. exponential search, instead of the typically
loosely bounded binary search. This produces a tight upper bound (within
2x) on the field count to then perform the binary search with.

As an upside of this change, the compiler-specific limit placed on the
upper bound on the field count to stay within compiler limits could be
removed.
2024-10-09 14:12:39 +03:00
Antony Polukhin
8cd1a9675d Merge branch 'develop' of github.com:boostorg/pfr into develop 2024-09-15 19:35:48 +03:00
Antony Polukhin
4d912c1925 Fix warning about GCC not being aware of the -Wundefined-var-template (fixes #166) 2024-09-15 19:35:21 +03:00
Antony Polukhin
e1a0832a0e Reflect up to 200 fields by default in c++17 implementation via structured bindings (#181) 2024-09-13 19:15:10 +03:00
Anarthal (Rubén Pérez)
73938e0936 Fix unused warnings in core_name14_disabled.hpp (#183)
Fixes #182
2024-09-13 19:03:12 +03:00
Antony Polukhin
e4cbbc78f0 Better headers organization (#180) 2024-09-13 14:24:21 +03:00
Antony Polukhin
6591a8609d Fix pragma directive (fixes #175) 2024-09-13 12:50:43 +03:00
Lena
3d090e7c6f Add function for_each_field_with_name (#171) 2024-09-13 11:57:49 +03:00
René Ferdinand Rivera Morell
e1e908e804 Add support for modular build structure. (#174) 2024-08-24 12:34:29 +03:00
Antony Polukhin
60391652fa Initial support for C++20 modules (#177) 2024-08-15 10:59:07 +03:00
Antony Polukhin
dec9341546 Update ci.yml (#178) 2024-08-14 20:28:49 +03:00
Antony Polukhin
449bf360f7 Workaround MSVC bogus warning (fixes #167) 2024-04-01 12:18:52 +03:00
Denis Mikhailov
5f857d5503 Get rid of cast_to_layout_compatible (#154) 2024-02-17 16:47:03 +03:00
Antony Polukhin
9b90f2f6bb CI fixes (#161) 2024-02-16 08:41:05 +03:00
Antony Polukhin
8f3b819b1e Allow throwing exceptions from pfr::structure_to_tuple (fixes #155) … (#160)
…and fix some warnings
2024-02-15 10:10:46 +03:00
Antony Polukhin
4a973c5eb4 Update docs by not using is_aggregate (fixes #158) and by describing the get_name implementation (fixes #150) 2024-02-14 21:00:23 +03:00
Antony Polukhin
4c15f217f4 Merge pull request #152 from schaumb/get_name
Addressing the limitation of get_name
2024-01-28 11:52:57 +03:00
Antony Polukhin
e969c57be5 Docs update 2024-01-07 13:14:25 +03:00
Antony Polukhin
16d771f498 Update copyright years 2024-01-07 13:12:44 +03:00
bela
16a97bb1f5 Fix sample compilation 2023-11-30 11:41:58 +01:00
bela
8a0447b486 Fix missing ; 2023-11-30 11:31:06 +01:00
bela
b674d728be revert field_name and SimpleAggregate comment 2023-11-30 10:14:01 +01:00
bela
5b55480c65 Addressing the limitation of get_name 2023-11-30 10:09:09 +01:00
Denis Mikhailov
98789f610a Fix get_name on clang for MSVC (#149) 2023-11-29 09:32:30 +03:00
Denis Mikhailov
c695aa0b32 Improve diagnostic for attempt to use get_name with non-external (#146)
Co-authored-by: Antony Polukhin <antoshkka@gmail.com>
2023-11-26 11:52:17 +03:00
114 changed files with 8644 additions and 343 deletions

View File

@@ -17,6 +17,9 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: gcc-14
cxxstd: "03,11,14,17,20"
os: ubuntu-24.04
- toolset: gcc-12 # Do not remove! It is the only toolset that tests misc/strip_boost_namespace.sh
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
@@ -41,10 +44,7 @@ jobs:
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-9"
- toolset: clang-14
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
- toolset: clang-13
- toolset: clang-15
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
# - toolset: clang
@@ -78,19 +78,19 @@ jobs:
cd ..
git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem
git submodule update --init --depth 10 --jobs 2 tools/boostdep libs/filesystem tools/inspect
python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem
rm -rf libs/$LIBRARY/*
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build
./b2 variant=debug tools/inspect/build
- name: Run tests
run: |
cd ../boost-root
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
./b2 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
dist/bin/inspect libs/$LIBRARY
- name: Test boost namespace stripping
@@ -145,6 +145,10 @@ jobs:
addrmd: 64
os: windows-2022
threads: "-j1"
- toolset: clang-win
cxxstd: "14,17,2a,latest"
addrmd: 32,64
os: windows-2022
runs-on: ${{matrix.os}}
@@ -168,7 +172,7 @@ jobs:
git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
git submodule update --init --depth 10 --jobs 2 tools/boostdep
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY%
cmd /c bootstrap
b2 -d0 headers

View File

@@ -1,5 +1,6 @@
# Generated by `boostdep --cmake pfr`
# Copyright 2020 Peter Dimov
# Copyright (c) 2016-2024 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
@@ -12,9 +13,11 @@ add_library(Boost::pfr ALIAS boost_pfr)
target_include_directories(boost_pfr INTERFACE include)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.28.0" AND BUILD_MODULE)
add_subdirectory(module)
endif()
if (BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

20
build.jam Normal file
View File

@@ -0,0 +1,20 @@
# Copyright René Ferdinand Rivera Morell 2023-2024
# 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)
require-b2 5.2 ;
project /boost/pfr
: common-requirements
<include>include
;
explicit
[ alias boost_pfr : : : : <library>$(boost_dependencies) ]
[ alias all : boost_pfr test ]
;
call-if : boost-library pfr
;

View File

@@ -18,7 +18,7 @@ project pfr/doc ;
#
# Common params for doxygen
#
#
local doxygen_params =
<doxygen:param>EXTRACT_ALL=NO
@@ -43,8 +43,8 @@ local doxygen_params =
doxygen autodoc_pfr
:
[ glob ../../../boost/pfr.hpp ]
[ glob ../../../boost/pfr/*.hpp ]
[ glob ../include/boost/pfr.hpp ]
[ glob ../include/boost/pfr/*.hpp ]
:
$(doxygen_params)
<xsl:param>"boost.doxygen.reftitle=Reference Section of PFR"

View File

@@ -1,7 +1,7 @@
[library Boost.PFR
[quickbook 1.6]
[version 2.2]
[copyright 2016-2023 Antony Polukhin]
[copyright 2016-2024 Antony Polukhin]
[category Language Features Emulation]
[license
Distributed under the Boost Software License, Version 1.0.
@@ -161,7 +161,7 @@ void Write(Writer& writer, int value);
void Write(Writer& writer, std::string_view value);
template <typename T>
std::enable_if_t<std::is_aggregate_v<T>> Write(Writer& writer, const T& value) {
std::enable_if_t<boost::pfr::is_implicitly_reflectable_v<T>> Write(Writer& writer, const T& value) {
boost::pfr::for_each_field(
value, [&writer](const auto& field) { Write(writer, field); });
}
@@ -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] ]
@@ -490,9 +493,7 @@ struct aggregate : empty { // not a SimpleAggregate
```
The library may work with aggregates that don't satisfy the requirements of `SimpleAggregate`, but the behavior tends to be non-portable.
Boost.PFRs extraction of field name works with a `SimpleAggregate` with non-internal linkage (with aggregats that could be used as `extern T t;`).
Do not use this functionality with anonymous structures, local structures
or a structure defined inside anonymous namespace as the behavior tends to be non-portable.
Boost.PFRs extraction of field name works with only `SimpleAggregate` types.
[h2 Configuration Macro]
@@ -551,8 +552,44 @@ parameters provided to `BOOST_PFR_CORE_NAME_PARSING` macro [*and] the initial ou
[endsect]
[section PFR as a C++20 module]
[caution C++20 PFR module support is on early stage, targets and flags may change in the future]
If using CMake of version 3.28.0 or higher define CMake option `-DBUILD_MODULE=1`
to make the `Boost::pfr_module` and `Boost::pfr_module_migration` libraries
available. With `Boost::pfr_module` C++20 module Boost.PFR could be used:
[import ../module/usage_sample.cpp]
[pfr_module_example]
The `Boost::pfr_module_migration` CMake target gives an ability to
mix includes and imports of the PFR library in different translation units.
If not using CMake, then the module could be build manually from the
`module/pfr.cppm` file. If mixing of includes in imports is desired, additionally
define `BOOST_PFR_ATTACH_TO_GLOBAL_MODULE` preprocessor macro to attach all the
module entities to a global module and avoid ODR issues.
For manual module build the following commands could be used for clang compiler:
```
cd pfr/module
clang++ -I ../include -std=c++20 --precompile -x c++-module pfr.cppm
```
After that, the module could be used in the following way:
```
clang++ -std=c++20 -fmodule-file=pfr.pcm pfr.pcm usage_sample.cpp
```
[endsect]
[section How it works]
[h2 Fields count detection and getting references to members]
Short description:
# at compile-time: use aggregate initialization to detect fields count in user-provided structure
@@ -579,6 +616,17 @@ Long description of some basics: [@https://youtu.be/UlNUNxLtBI0 Antony Polukhin:
Long description of some basics of C++14 with [link boost_pfr.limitations_and_configuration [*BOOST_PFR_USE_LOOPHOLE == 0]]: [@https://youtu.be/abdeAew3gmQ Antony Polukhin: C++14 Reflections Without Macros, Markup nor External Tooling].
Description of the [*BOOST_PFR_USE_LOOPHOLE == 1] technique by its inventor Alexandr Poltavsky [@http://alexpolt.github.io/type-loophole.html in his blog].
[h2 Field name retrieval]
# at compile-time:
* Get references to members of an object of type `T` in `constexpr` function
* Feed the reference from previous as a template parameter to a `constexpr` function with `template <auto member_ptr>`.
That function returns `__PRETTY_FUNCTION__` or some other vendor specific macro that prints the whole name of a function
along with the template arguments.
* The returned value from previous step contains the member name ([@https://godbolt.org/z/K4aWdcE9G godbolt example]). Do some
compiler specific parsing of the value and make a `std::string_view` that contains only the member name.
# at run-time: return the `std::string_view` with the member name.
[endsect]
[section Acknowledgements]

View File

@@ -1,4 +1,4 @@
// Copyright 2016-2023 Antony Polukhin
// Copyright 2016-2024 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright 2016-2023 Antony Polukhin
// Copyright 2016-2024 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
@@ -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
@@ -106,19 +135,23 @@ void test_examples() {
//]
}
// Disabled from testing since it's unportable
#if 0
// 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_get_name
// Get name of field by index
struct sample {
int f1;
long f2;
int f_int;
long f_long;
};
std::cout << boost::pfr::get_name<0, sample>()
<< boost::pfr::get_name<1, sample>(); // Outputs: f1 f2
<< boost::pfr::get_name<1, sample>(); // Outputs: f_int f_long
//]
}
#endif

View File

@@ -1,4 +1,4 @@
// Copyright 2016-2023 Antony Polukhin
// Copyright 2016-2024 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 Antony Polukhin
// Copyright (c) 2022 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -113,7 +113,7 @@
#ifndef BOOST_PFR_CORE_NAME_PARSING
# if defined(_MSC_VER)
# if defined(_MSC_VER) && !defined(__clang__)
# define BOOST_PFR_CORE_NAME_PARSING (sizeof("auto __cdecl boost::pfr::detail::name_of_field_impl<") - 1, sizeof(">(void) noexcept") - 1, backward("->"))
# elif defined(__clang__)
# define BOOST_PFR_CORE_NAME_PARSING (sizeof("auto boost::pfr::detail::name_of_field_impl() [MsvcWorkaround = ") - 1, sizeof("}]") - 1, backward("."))
@@ -145,4 +145,12 @@
#undef BOOST_PFR_NOT_SUPPORTED
#ifndef BOOST_PFR_BEGIN_MODULE_EXPORT
# define BOOST_PFR_BEGIN_MODULE_EXPORT
#endif
#ifndef BOOST_PFR_END_MODULE_EXPORT
# define BOOST_PFR_END_MODULE_EXPORT
#endif
#endif // BOOST_PFR_CONFIG_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -13,7 +13,7 @@
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/stdtuple.hpp>
#include <boost/pfr/detail/for_each_field_impl.hpp>
#include <boost/pfr/detail/for_each_field.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/tie_from_structure_tuple.hpp>
@@ -29,6 +29,8 @@
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
/// \brief Returns reference or const reference to a field with index `I` in \aggregate `val`.
/// Overload taking the type `U` returns reference or const reference to a field
/// with provided type `U` in \aggregate `val` if there's only one field of such type in `val`.
@@ -140,7 +142,7 @@ using tuple_element_t = typename tuple_element<I, T>::type;
/// assert(get<0>(t) == 10);
/// \endcode
template <class T>
constexpr auto structure_to_tuple(const T& val) noexcept {
constexpr auto structure_to_tuple(const T& val) {
return detail::make_stdtuple_from_tietuple(
detail::tie_as_tuple(val),
detail::make_index_sequence< tuple_size_v<T> >()
@@ -221,24 +223,7 @@ constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&
/// \endcode
template <class T, class F>
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(
value,
[f = std::forward<F>(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),
detail::make_index_sequence<fields_count_val_in_lambda>{},
std::is_rvalue_reference<T&&>{}
);
},
detail::make_index_sequence<fields_count_val>{}
);
return ::boost::pfr::detail::for_each_field(std::forward<T>(value), std::forward<F>(func));
}
/// \brief std::tie-like function that allows assigning to tied values from aggregates.
@@ -260,6 +245,8 @@ constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Eleme
return detail::tie_from_structure_tuple<Elements...>(args...);
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_CORE_HPP

View File

@@ -33,6 +33,8 @@
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
/// \brief Returns name of a field with index `I` in \aggregate `T`.
///
/// \b Example:
@@ -82,7 +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

View File

@@ -1,75 +0,0 @@
// Copyright (c) 2016-2023 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_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP
#define BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <type_traits>
#include <utility> // metaprogramming stuff
#include <boost/pfr/detail/rvalue_t.hpp>
namespace boost { namespace pfr { namespace detail {
template <class T, class U>
constexpr void static_assert_layout_compatible() noexcept {
static_assert(
std::alignment_of<T>::value == std::alignment_of<U>::value,
"====================> Boost.PFR: Alignment check failed, probably your structure has user-defined alignment for the whole structure or for some of the fields."
);
static_assert(sizeof(T) == sizeof(U), "====================> Boost.PFR: Size check failed, probably your structure has bitfields or user-defined alignment.");
}
/// @cond
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
/// @endcond
template <class To, class From>
MAY_ALIAS const To& cast_to_layout_compatible(const From& val) noexcept {
MAY_ALIAS const To* const t = reinterpret_cast<const To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS const volatile To& cast_to_layout_compatible(const volatile From& val) noexcept {
MAY_ALIAS const volatile To* const t = reinterpret_cast<const volatile To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS volatile To& cast_to_layout_compatible(volatile From& val) noexcept {
MAY_ALIAS volatile To* const t = reinterpret_cast<volatile To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS To& cast_to_layout_compatible(From& val) noexcept {
MAY_ALIAS To* const t = reinterpret_cast<To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
#ifdef BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING
template <class To, class From>
To&& cast_to_layout_compatible(rvalue_t<From> val) noexcept = delete;
#endif
#undef MAY_ALIAS
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 Antony Polukhin
// Copyright (c) 2022 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,8 +9,12 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <utility> // metaprogramming stuff
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/offset_based_getter.hpp>

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2017-2018 Alexandr Poltavsky, Antony Polukhin.
// Copyright (c) 2019-2023 Antony Polukhin.
// Copyright (c) 2019-2024 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)
@@ -24,10 +24,13 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <utility>
#endif
#include <boost/pfr/detail/cast_to_layout_compatible.hpp> // still needed for enums
#include <boost/pfr/detail/offset_based_getter.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/make_flat_tuple_of_references.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -13,16 +13,23 @@
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/core.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/stdarray.hpp>
#include <boost/pfr/detail/fake_object.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/for_each_field.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/stdarray.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <string_view>
#include <array>
#include <memory> // for std::addressof
#endif
namespace boost { namespace pfr { namespace detail {
@@ -99,7 +106,7 @@ consteval auto name_of_field_impl() noexcept {
static_assert(!sv.empty(),
"====================> Boost.PFR: Field reflection parser configured in a wrong way. "
"Please define the BOOST_PFR_FUNCTION_SIGNATURE to a compiler specific macro, "
"that outputs the whole function signature including non-type template parameters."
"that outputs the whole function signature including non-type template parameters."
);
constexpr auto skip = detail::make_core_name_skip BOOST_PFR_CORE_NAME_PARSING;
@@ -167,7 +174,7 @@ consteval auto name_of_field() noexcept {
&& std::string_view{
detail::name_of_field_impl<
core_name_skip, detail::make_clang_wrapper(std::addressof(
fake_object<core_name_skip>.size_at_begin
detail::fake_object<core_name_skip>().size_at_begin
))
>().data()
} == "size_at_begin",
@@ -187,7 +194,7 @@ consteval auto name_of_field() noexcept {
template <class T, std::size_t I>
inline constexpr auto stored_name_of_field = detail::name_of_field<T,
detail::make_clang_wrapper(std::addressof(detail::sequence_tuple::get<I>(
detail::tie_as_tuple(detail::fake_object<T>)
detail::tie_as_tuple(detail::fake_object<T>())
)))
>();
@@ -236,6 +243,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::detail::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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,8 +9,12 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <functional>
#include <type_traits>
#endif
namespace boost { namespace pfr { namespace detail {
///////////////////// `value` is true if Detector<Tleft, Tright> does not compile (SFINAE)

View File

@@ -1,4 +1,5 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
// Copyright (c) 2024-2024 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)
@@ -14,12 +15,40 @@
#include <boost/pfr/detail/config.hpp>
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wundefined-internal"
# pragma clang diagnostic ignored "-Wundefined-var-template"
#endif
namespace boost { namespace pfr { namespace detail {
// This class has external linkage while T has not sure.
template <class T>
extern const T fake_object;
struct wrapper {
const T value;
};
// This variable servers as a link-time assert.
// If linker requires it, then `fake_object()` is used at runtime.
template <class T>
extern const wrapper<T> do_not_use_PFR_with_local_types;
// For returning non default constructible types, it's exclusively used in member name retrieval.
//
// Neither std::declval nor boost::pfr::detail::unsafe_declval are usable there.
// This takes advantage of C++20 features, while boost::pfr::detail::unsafe_declval works
// with the former standards.
template <class T>
constexpr const T& fake_object() noexcept {
return do_not_use_PFR_with_local_types<T>.value;
}
}}} // namespace boost::pfr::detail
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#endif // BOOST_PFR_DETAIL_FAKE_OBJECT_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -12,9 +12,14 @@
#include <boost/pfr/detail/size_t_.hpp>
#include <boost/pfr/detail/unsafe_declval.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <climits> // CHAR_BIT
#include <cstdint> // SIZE_MAX
#include <type_traits>
#include <utility> // metaprogramming stuff
#endif
#ifdef __clang__
# pragma clang diagnostic push
@@ -26,6 +31,11 @@
namespace boost { namespace pfr { namespace detail {
///////////////////// min without including <algorithm>
constexpr std::size_t min_of_size_t(std::size_t a, std::size_t b) noexcept {
return b < a ? b : a;
}
///////////////////// Structure that can be converted to reference to anything
struct ubiq_lref_constructor {
std::size_t ignore;
@@ -46,6 +56,14 @@ struct ubiq_rref_constructor {
}
};
///////////////////// Hand-made is_complete<T> trait
template <typename T, typename = void>
struct is_complete : std::false_type
{};
template <typename T>
struct is_complete<T, decltype(void(sizeof(T)))> : std::integral_constant<bool, true>
{};
#ifndef __cpp_lib_is_aggregate
///////////////////// Hand-made is_aggregate_initializable_n<T> trait
@@ -74,8 +92,16 @@ template <class T> struct is_single_field_and_aggregate_initializable<1, T>: std
// Before C++20 aggregates could be constructed from `decltype(ubiq_?ref_constructor{I})...` but type traits report that
// there's no constructor from `decltype(ubiq_?ref_constructor{I})...`
// Special case for N == 1: `std::is_constructible<T, ubiq_?ref_constructor>` returns true if N == 1 and T is copy/move constructible.
template <class T, std::size_t N>
template <class T, std::size_t N, class /*Enable*/ = void>
struct is_aggregate_initializable_n {
static constexpr bool value =
std::is_empty<T>::value
|| std::is_array<T>::value
;
};
template <class T, std::size_t N>
struct is_aggregate_initializable_n<T, N, std::enable_if_t<std::is_class<T>::value && !std::is_empty<T>::value>> {
template <std::size_t ...I>
static constexpr bool is_not_constructible_n(std::index_sequence<I...>) noexcept {
return (!std::is_constructible<T, decltype(ubiq_lref_constructor{I})...>::value && !std::is_constructible<T, decltype(ubiq_rref_constructor{I})...>::value)
@@ -83,12 +109,7 @@ struct is_aggregate_initializable_n {
;
}
static constexpr bool value =
std::is_empty<T>::value
|| std::is_array<T>::value
|| std::is_fundamental<T>::value
|| is_not_constructible_n(detail::make_index_sequence<N>{})
;
static constexpr bool value = is_not_constructible_n(detail::make_index_sequence<N>{});
};
#endif // #ifndef __cpp_lib_is_aggregate
@@ -127,16 +148,16 @@ struct ubiq_rref_base_asserting {
}
};
template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = typename std::enable_if<std::is_copy_constructible<T>::value>::type>
template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = std::enable_if_t<std::is_copy_constructible<T>::value>>
constexpr auto assert_first_not_base(std::index_sequence<I0, I...>) noexcept
-> typename std::add_pointer<decltype(T{ ubiq_lref_base_asserting<T>{}, ubiq_lref_constructor{I}... })>::type
-> std::add_pointer_t<decltype(T{ ubiq_lref_base_asserting<T>{}, ubiq_lref_constructor{I}... })>
{
return nullptr;
}
template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = typename std::enable_if<!std::is_copy_constructible<T>::value>::type>
template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = std::enable_if_t<!std::is_copy_constructible<T>::value>>
constexpr auto assert_first_not_base(std::index_sequence<I0, I...>) noexcept
-> typename std::add_pointer<decltype(T{ ubiq_rref_base_asserting<T>{}, ubiq_rref_constructor{I}... })>::type
-> std::add_pointer_t<decltype(T{ ubiq_rref_base_asserting<T>{}, ubiq_rref_constructor{I}... })>
{
return nullptr;
}
@@ -147,17 +168,40 @@ constexpr void* assert_first_not_base(std::index_sequence<>) noexcept
return nullptr;
}
///////////////////// Helper for SFINAE on fields count
template <class T, std::size_t... I, class /*Enable*/ = typename std::enable_if<std::is_copy_constructible<T>::value>::type>
constexpr auto enable_if_constructible_helper(std::index_sequence<I...>) noexcept
-> typename std::add_pointer<decltype(T{ ubiq_lref_constructor{I}... })>::type;
template <class T, std::size_t N>
constexpr void assert_first_not_base(int) noexcept {}
template <class T, std::size_t... I, class /*Enable*/ = typename std::enable_if<!std::is_copy_constructible<T>::value>::type>
constexpr auto enable_if_constructible_helper(std::index_sequence<I...>) noexcept
-> typename std::add_pointer<decltype(T{ ubiq_rref_constructor{I}... })>::type;
template <class T, std::size_t N>
constexpr auto assert_first_not_base(long) noexcept
-> std::enable_if_t<std::is_class<T>::value>
{
detail::assert_first_not_base<T>(detail::make_index_sequence<N>{});
}
template <class T, std::size_t N, class /*Enable*/ = decltype( enable_if_constructible_helper<T>(detail::make_index_sequence<N>()) ) >
using enable_if_constructible_helper_t = std::size_t;
///////////////////// Helpers for initializable detection
// Note that these take O(N) compile time and memory!
template <class T, std::size_t... I, class /*Enable*/ = std::enable_if_t<std::is_copy_constructible<T>::value>>
constexpr auto enable_if_initializable_helper(std::index_sequence<I...>) noexcept
-> std::add_pointer_t<decltype(T{ubiq_lref_constructor{I}...})>;
template <class T, std::size_t... I, class /*Enable*/ = std::enable_if_t<!std::is_copy_constructible<T>::value>>
constexpr auto enable_if_initializable_helper(std::index_sequence<I...>) noexcept
-> std::add_pointer_t<decltype(T{ubiq_rref_constructor{I}...})>;
template <class T, std::size_t N, class U = std::size_t, class /*Enable*/ = decltype(detail::enable_if_initializable_helper<T>(detail::make_index_sequence<N>()))>
using enable_if_initializable_helper_t = U;
template <class T, std::size_t N>
constexpr auto is_initializable(long) noexcept
-> detail::enable_if_initializable_helper_t<T, N, bool>
{
return true;
}
template <class T, std::size_t N>
constexpr bool is_initializable(int) noexcept {
return false;
}
///////////////////// Helpers for range size detection
template <std::size_t Begin, std::size_t Last>
@@ -166,92 +210,158 @@ using is_one_element_range = std::integral_constant<bool, Begin == Last>;
using multi_element_range = std::false_type;
using one_element_range = std::true_type;
///////////////////// Non greedy fields count search. Templates instantiation depth is log(sizeof(T)), templates instantiation count is log(sizeof(T)).
template <class T, std::size_t Begin, std::size_t Middle>
constexpr std::size_t detect_fields_count(detail::one_element_range, long) noexcept {
///////////////////// Fields count next expected compiler limitation
constexpr std::size_t fields_count_compiler_limitation_next(std::size_t n) noexcept {
#if defined(_MSC_VER) && (_MSC_VER <= 1920)
if (n < 1024)
return 1024;
#else
static_cast<void>(n);
#endif
return SIZE_MAX;
}
///////////////////// Fields count upper bound based on sizeof(T)
template <class T>
constexpr std::size_t fields_count_upper_bound_loose() noexcept {
return sizeof(T) * CHAR_BIT;
}
///////////////////// Fields count binary search.
// Template instantiation: depth is O(log(result)), count is O(log(result)), cost is O(result * log(result)).
template <class T, std::size_t Begin, std::size_t Last>
constexpr std::size_t fields_count_binary_search(detail::one_element_range, long) noexcept {
static_assert(
Begin == Middle,
Begin == Last,
"====================> Boost.PFR: Internal logic error."
);
return Begin;
}
template <class T, std::size_t Begin, std::size_t Middle>
constexpr std::size_t detect_fields_count(detail::multi_element_range, int) noexcept;
template <class T, std::size_t Begin, std::size_t Last>
constexpr std::size_t fields_count_binary_search(detail::multi_element_range, int) noexcept;
template <class T, std::size_t Begin, std::size_t Middle>
constexpr auto detect_fields_count(detail::multi_element_range, long) noexcept
-> detail::enable_if_constructible_helper_t<T, Middle>
template <class T, std::size_t Begin, std::size_t Last>
constexpr auto fields_count_binary_search(detail::multi_element_range, long) noexcept
-> detail::enable_if_initializable_helper_t<T, (Begin + Last + 1) / 2>
{
constexpr std::size_t next_v = Middle + (Middle - Begin + 1) / 2;
return detail::detect_fields_count<T, Middle, next_v>(detail::is_one_element_range<Middle, next_v>{}, 1L);
}
template <class T, std::size_t Begin, std::size_t Middle>
constexpr std::size_t detect_fields_count(detail::multi_element_range, int) noexcept {
constexpr std::size_t next_v = Begin + (Middle - Begin) / 2;
return detail::detect_fields_count<T, Begin, next_v>(detail::is_one_element_range<Begin, next_v>{}, 1L);
}
///////////////////// Greedy search. Templates instantiation depth is log(sizeof(T)), templates instantiation count is log(sizeof(T))*T in worst case.
template <class T, std::size_t N>
constexpr auto detect_fields_count_greedy_remember(long) noexcept
-> detail::enable_if_constructible_helper_t<T, N>
{
return N;
}
template <class T, std::size_t N>
constexpr std::size_t detect_fields_count_greedy_remember(int) noexcept {
return 0;
constexpr std::size_t next_v = (Begin + Last + 1) / 2;
return detail::fields_count_binary_search<T, next_v, Last>(detail::is_one_element_range<next_v, Last>{}, 1L);
}
template <class T, std::size_t Begin, std::size_t Last>
constexpr std::size_t detect_fields_count_greedy(detail::one_element_range) noexcept {
constexpr std::size_t fields_count_binary_search(detail::multi_element_range, int) noexcept {
constexpr std::size_t next_v = (Begin + Last + 1) / 2 - 1;
return detail::fields_count_binary_search<T, Begin, next_v>(detail::is_one_element_range<Begin, next_v>{}, 1L);
}
template <class T, std::size_t Begin, std::size_t N>
constexpr std::size_t fields_count_upper_bound(int, int) noexcept {
return N - 1;
}
template <class T, std::size_t Begin, std::size_t N>
constexpr auto fields_count_upper_bound(long, long) noexcept
-> std::enable_if_t<(N > detail::fields_count_upper_bound_loose<T>()), std::size_t>
{
static_assert(
!detail::is_initializable<T, detail::fields_count_upper_bound_loose<T>() + 1>(1L),
"====================> Boost.PFR: Types with user specified constructors (non-aggregate initializable types) are not supported.");
return detail::fields_count_upper_bound_loose<T>();
}
template <class T, std::size_t Begin, std::size_t N>
constexpr auto fields_count_upper_bound(long, int) noexcept
-> detail::enable_if_initializable_helper_t<T, N>
{
constexpr std::size_t next_optimal = Begin + (N - Begin) * 2;
constexpr std::size_t next = detail::min_of_size_t(next_optimal, detail::fields_count_compiler_limitation_next(N));
return detail::fields_count_upper_bound<T, Begin, next>(1L, 1L);
}
///////////////////// Fields count lower bound linear search.
// Template instantiation: depth is O(log(result)), count is O(result), cost is O(result^2).
template <class T, std::size_t Begin, std::size_t Last, class RangeSize, std::size_t Result>
constexpr std::size_t fields_count_lower_bound(RangeSize, size_t_<Result>) noexcept {
return Result;
}
template <class T, std::size_t Begin, std::size_t Last>
constexpr std::size_t fields_count_lower_bound(detail::one_element_range, size_t_<0> = {}) noexcept {
static_assert(
Begin == Last,
"====================> Boost.PFR: Internal logic error."
);
return detail::detect_fields_count_greedy_remember<T, Begin>(1L);
return detail::is_initializable<T, Begin>(1L) ? Begin : 0;
}
template <class T, std::size_t Begin, std::size_t Last>
constexpr std::size_t detect_fields_count_greedy(detail::multi_element_range) noexcept {
constexpr std::size_t fields_count_lower_bound(detail::multi_element_range, size_t_<0> = {}) noexcept {
// Binary partition to limit template depth.
constexpr std::size_t middle = Begin + (Last - Begin) / 2;
constexpr std::size_t fields_count_big_range = detail::detect_fields_count_greedy<T, middle + 1, Last>(
detail::is_one_element_range<middle + 1, Last>{}
constexpr std::size_t result_maybe = detail::fields_count_lower_bound<T, Begin, middle>(
detail::is_one_element_range<Begin, middle>{}
);
constexpr std::size_t small_range_begin = (fields_count_big_range ? 0 : Begin);
constexpr std::size_t small_range_last = (fields_count_big_range ? 0 : middle);
constexpr std::size_t fields_count_small_range = detail::detect_fields_count_greedy<T, small_range_begin, small_range_last>(
detail::is_one_element_range<small_range_begin, small_range_last>{}
return detail::fields_count_lower_bound<T, middle + 1, Last>(
detail::is_one_element_range<middle + 1, Last>{},
size_t_<result_maybe>{}
);
return fields_count_big_range ? fields_count_big_range : fields_count_small_range;
}
///////////////////// Choosing between array size, greedy and non greedy search.
template <class T, std::size_t N>
constexpr auto detect_fields_count_dispatch(size_t_<N>, long, long) noexcept
-> typename std::enable_if<std::is_array<T>::value, std::size_t>::type
template <class T, std::size_t Begin, std::size_t Result>
constexpr std::size_t fields_count_lower_bound_unbounded(int, size_t_<Result>) noexcept {
return Result;
}
template <class T, std::size_t Begin>
constexpr auto fields_count_lower_bound_unbounded(long, size_t_<0>) noexcept
-> std::enable_if_t<(Begin >= detail::fields_count_upper_bound_loose<T>()), std::size_t>
{
return sizeof(T) / sizeof(typename std::remove_all_extents<T>::type);
static_assert(
detail::is_initializable<T, detail::fields_count_upper_bound_loose<T>()>(1L),
"====================> Boost.PFR: Type must be aggregate initializable.");
return detail::fields_count_upper_bound_loose<T>();
}
template <class T, std::size_t N>
constexpr auto detect_fields_count_dispatch(size_t_<N>, long, int) noexcept
template <class T, std::size_t Begin>
constexpr std::size_t fields_count_lower_bound_unbounded(int, size_t_<0>) noexcept {
constexpr std::size_t last = detail::min_of_size_t(Begin * 2, detail::fields_count_upper_bound_loose<T>()) - 1;
constexpr std::size_t result_maybe = detail::fields_count_lower_bound<T, Begin, last>(
detail::is_one_element_range<Begin, last>{}
);
return detail::fields_count_lower_bound_unbounded<T, last + 1>(1L, size_t_<result_maybe>{});
}
///////////////////// Choosing between array size, unbounded binary search, and linear search followed by unbounded binary search.
template <class T>
constexpr auto fields_count_dispatch(long, long, std::false_type /*are_preconditions_met*/) noexcept {
return 0;
}
template <class T>
constexpr auto fields_count_dispatch(long, long, std::true_type /*are_preconditions_met*/) noexcept
-> std::enable_if_t<std::is_array<T>::value, std::size_t>
{
return sizeof(T) / sizeof(std::remove_all_extents_t<T>);
}
template <class T>
constexpr auto fields_count_dispatch(long, int, std::true_type /*are_preconditions_met*/) noexcept
-> decltype(sizeof(T{}))
{
constexpr std::size_t middle = N / 2 + 1;
return detail::detect_fields_count<T, 0, middle>(detail::multi_element_range{}, 1L);
constexpr std::size_t typical_fields_count = 4;
constexpr std::size_t last = detail::fields_count_upper_bound<T, typical_fields_count / 2, typical_fields_count>(1L, 1L);
return detail::fields_count_binary_search<T, 0, last>(detail::is_one_element_range<0, last>{}, 1L);
}
template <class T, std::size_t N>
constexpr std::size_t detect_fields_count_dispatch(size_t_<N>, int, int) noexcept {
// T is not default aggregate initialzable. It means that at least one of the members is not default constructible,
// so we have to check all the aggregate initializations for T up to N parameters and return the bigest succeeded
// (we can not use binary search for detecting fields count).
return detail::detect_fields_count_greedy<T, 0, N>(detail::multi_element_range{});
template <class T>
constexpr std::size_t fields_count_dispatch(int, int, std::true_type /*are_preconditions_met*/) noexcept {
// T is not default aggregate initializable. This means that at least one of the members is not default-constructible.
// Use linear search to find the smallest valid initializer, after which we unbounded binary search for the largest.
constexpr std::size_t begin = detail::fields_count_lower_bound_unbounded<T, 1>(1L, size_t_<0>{});
constexpr std::size_t last = detail::fields_count_upper_bound<T, begin, begin + 1>(1L, 1L);
return detail::fields_count_binary_search<T, begin, last>(detail::is_one_element_range<begin, last>{}, 1L);
}
///////////////////// Returns fields count
@@ -259,32 +369,52 @@ template <class T>
constexpr std::size_t fields_count() noexcept {
using type = std::remove_cv_t<T>;
constexpr bool type_is_complete = detail::is_complete<type>::value;
static_assert(
!std::is_reference<type>::value,
type_is_complete,
"====================> Boost.PFR: Type must be complete."
);
constexpr bool type_is_not_a_reference = !std::is_reference<type>::value
|| !type_is_complete // do not show assert if previous check failed
;
static_assert(
type_is_not_a_reference,
"====================> Boost.PFR: Attempt to get fields count on a reference. This is not allowed because that could hide an issue and different library users expect different behavior in that case."
);
#if !BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
static_assert(
#if BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
constexpr bool type_fields_are_move_constructible = true;
#else
constexpr bool type_fields_are_move_constructible =
std::is_copy_constructible<std::remove_all_extents_t<type>>::value || (
std::is_move_constructible<std::remove_all_extents_t<type>>::value
&& std::is_move_assignable<std::remove_all_extents_t<type>>::value
),
)
|| !type_is_not_a_reference // do not show assert if previous check failed
;
static_assert(
type_fields_are_move_constructible,
"====================> Boost.PFR: Type and each field in the type must be copy constructible (or move constructible and move assignable)."
);
#endif // #if !BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
constexpr bool type_is_not_polymorphic = !std::is_polymorphic<type>::value;
static_assert(
!std::is_polymorphic<type>::value,
type_is_not_polymorphic,
"====================> Boost.PFR: Type must have no virtual function, because otherwise it is not aggregate initializable."
);
#ifdef __cpp_lib_is_aggregate
static_assert(
constexpr bool type_is_aggregate =
std::is_aggregate<type>::value // Does not return `true` for built-in types.
|| std::is_scalar<type>::value,
|| std::is_scalar<type>::value;
static_assert(
type_is_aggregate,
"====================> Boost.PFR: Type must be aggregate initializable."
);
#else
constexpr bool type_is_aggregate = true;
#endif
// Can't use the following. See the non_std_layout.cpp test.
@@ -295,26 +425,28 @@ constexpr std::size_t fields_count() noexcept {
// );
//#endif
#if defined(_MSC_VER) && (_MSC_VER <= 1920)
// Workaround for msvc compilers. Versions <= 1920 have a limit of max 1024 elements in template parameter pack
constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT >= 1024 ? 1024 : sizeof(type) * CHAR_BIT);
#else
constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT); // We multiply by CHAR_BIT because the type may have bitfields in T
#endif
constexpr bool no_errors =
type_is_complete && type_is_not_a_reference && type_fields_are_move_constructible
&& type_is_not_polymorphic && type_is_aggregate;
constexpr std::size_t result = detail::detect_fields_count_dispatch<type>(size_t_<max_fields_count>{}, 1L, 1L);
constexpr std::size_t result = detail::fields_count_dispatch<type>(1L, 1L, std::integral_constant<bool, no_errors>{});
detail::assert_first_not_base<type>(detail::make_index_sequence<result>{});
detail::assert_first_not_base<type, result>(1L);
#ifndef __cpp_lib_is_aggregate
constexpr bool type_is_aggregate_initializable_n =
detail::is_aggregate_initializable_n<type, result>::value // Does not return `true` for built-in types.
|| std::is_scalar<type>::value;
static_assert(
is_aggregate_initializable_n<type, result>::value,
type_is_aggregate_initializable_n,
"====================> Boost.PFR: Types with user specified constructors (non-aggregate initializable types) are not supported."
);
#else
constexpr bool type_is_aggregate_initializable_n = true;
#endif
static_assert(
result != 0 || std::is_empty<type>::value || std::is_fundamental<type>::value || std::is_reference<type>::value,
result != 0 || std::is_empty<type>::value || std::is_fundamental<type>::value || std::is_reference<type>::value || !no_errors || !type_is_aggregate_initializable_n,
"====================> Boost.PFR: If there's no other failed static asserts then something went wrong. Please report this issue to the github along with the structure you're reflecting."
);

View File

@@ -0,0 +1,50 @@
// Copyright (c) 2016-2024 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_DETAIL_FOR_EACH_FIELD_HPP
#define BOOST_PFR_DETAIL_FOR_EACH_FIELD_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits> // metaprogramming stuff
#endif
#include <boost/pfr/detail/core.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/for_each_field_impl.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
namespace boost { namespace pfr { namespace detail {
template <class T, class F>
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(
value,
[f = std::forward<F>(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),
detail::make_index_sequence<fields_count_val_in_lambda>{},
std::is_rvalue_reference<T&&>{}
);
},
detail::make_index_sequence<fields_count_val>{}
);
}
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_FOR_EACH_FIELD_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,7 +9,11 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <utility> // metaprogramming stuff
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/rvalue_t.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,8 +9,12 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <functional>
#include <cstdint>
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -10,6 +10,10 @@
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <iosfwd> // stream operators
#include <iomanip>
@@ -19,6 +23,8 @@
# endif
#endif
#endif
namespace boost { namespace pfr { namespace detail {
inline auto quoted_helper(const std::string& s) noexcept {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,7 +9,12 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <utility> // metaprogramming stuff
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/rvalue_t.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2018 Sergei Fedorov
// Copyright (c) 2019-2023 Antony Polukhin
// Copyright (c) 2019-2024 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)
@@ -10,9 +10,13 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <utility>
#include <cstddef>
#endif
namespace boost { namespace pfr { namespace detail {

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2017-2018 Chris Beck
// Copyright (c) 2019-2023 Antony Polukhin
// Copyright (c) 2019-2024 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)
@@ -10,9 +10,14 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <utility>
#include <memory> // std::addressof
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/rvalue_t.hpp>
#include <boost/pfr/detail/size_t_.hpp>

View File

@@ -10,7 +10,11 @@
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/traits_fwd.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits> // for std::is_aggregate
#endif
namespace boost { namespace pfr { namespace detail {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -7,8 +7,12 @@
#define BOOST_PFR_DETAIL_RVALUE_T_HPP
#pragma once
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#include <utility> // std::enable_if_t
#endif
// This header provides aliases rvalue_t and lvalue_t.
//

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -10,8 +10,12 @@
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <utility> // metaprogramming stuff
#include <cstddef> // std::size_t
#endif
///////////////////// Tuple that holds its values in the supplied order
namespace boost { namespace pfr { namespace detail { namespace sequence_tuple {
@@ -50,68 +54,68 @@ struct tuple_base<std::index_sequence<> > {
template <std::size_t N, class T>
constexpr T& get_impl(base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <std::size_t N, class T>
constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <std::size_t N, class T>
constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <std::size_t N, class T>
constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <std::size_t N, class T>
constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return std::forward<T>(t.value);
}
template <class T, std::size_t N>
constexpr T& get_by_type_impl(base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <class T, std::size_t N>
constexpr const T& get_by_type_impl(const base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <class T, std::size_t N>
constexpr volatile T& get_by_type_impl(volatile base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <class T, std::size_t N>
constexpr const volatile T& get_by_type_impl(const volatile base_from_member<N, T>& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return t.value;
}
template <class T, std::size_t N>
constexpr T&& get_by_type_impl(base_from_member<N, T>&& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return std::forward<T>(t.value);
}
template <class T, std::size_t N>
constexpr const T&& get_by_type_impl(const base_from_member<N, T>&& t) noexcept {
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.CallAndMessage)
return std::forward<T>(t.value);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,7 +9,11 @@
#include <boost/pfr/detail/config.hpp>
#include <cstddef> // metaprogramming stuff
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <cstddef>
#endif
namespace boost { namespace pfr { namespace detail {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -9,10 +9,14 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <utility> // metaprogramming stuff
#include <array>
#include <type_traits> // for std::common_type_t
#include <cstddef>
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -9,15 +9,20 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <utility> // metaprogramming stuff
#include <tuple>
#endif
#include <boost/pfr/detail/sequence_tuple.hpp>
namespace boost { namespace pfr { namespace detail {
template <class T, std::size_t... I>
constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence<I...>) {
(void)t; // workaround for MSVC 14.1 `warning C4100: 't': unreferenced formal parameter`
return std::make_tuple(
boost::pfr::detail::sequence_tuple::get<I>(t)...
);
@@ -25,6 +30,7 @@ constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence<I...>
template <class T, std::size_t... I>
constexpr auto make_stdtiedtuple_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
(void)t; // workaround for MSVC 14.1 `warning C4100: 't': unreferenced formal parameter`
return std::tie(
boost::pfr::detail::sequence_tuple::get<I>(t)...
);
@@ -32,6 +38,7 @@ constexpr auto make_stdtiedtuple_from_tietuple(const T& t, std::index_sequence<I
template <class T, std::size_t... I>
constexpr auto make_conststdtiedtuple_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
(void)t; // workaround for MSVC 14.1 `warning C4100: 't': unreferenced formal parameter`
return std::tuple<
std::add_lvalue_reference_t<std::add_const_t<
std::remove_reference_t<decltype(boost::pfr::detail::sequence_tuple::get<I>(t))>

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2018 Adam Butcher, Antony Polukhin
// Copyright (c) 2019-2023 Antony Polukhin
// Copyright (c) 2019-2024 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)
@@ -16,7 +16,11 @@
#include <boost/pfr/tuple_size.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <tuple>
#endif
namespace boost { namespace pfr { namespace detail {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2019-2023 Antony Polukhin.
// Copyright (c) 2019-2024 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)
@@ -9,7 +9,11 @@
#include <boost/pfr/detail/config.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits>
#endif
namespace boost { namespace pfr { namespace detail {

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -35,6 +35,8 @@
/// \b Synopsis:
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
///////////////////// Comparisons
/// \brief std::equal_to like comparator that returns \forcedlink{eq}(x, y)
@@ -216,6 +218,8 @@ template <class T> struct hash {
}
};
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_FUNCTORS_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -67,6 +67,8 @@ struct io_impl {
T value;
};
BOOST_PFR_BEGIN_MODULE_EXPORT
template <class Char, class Traits, class T>
enable_not_ostreamable_t<std::basic_ostream<Char, Traits>, T> operator<<(std::basic_ostream<Char, Traits>& out, io_impl<T>&& x) {
return out << boost::pfr::io_fields(std::forward<T>(x.value));
@@ -87,8 +89,12 @@ enable_istreamable_t<std::basic_istream<Char, Traits>, T> operator>>(std::basic_
return in >> x.value;
}
BOOST_PFR_END_MODULE_EXPORT
} // namespace detail
BOOST_PFR_BEGIN_MODULE_EXPORT
/// IO manipulator to read/write \aggregate `value` using its IO stream operators or using \forcedlink{io_fields} if operators are not available.
///
/// \b Example:
@@ -108,6 +114,8 @@ auto io(T&& value) noexcept {
return detail::io_impl<T>{std::forward<T>(value)};
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_IO_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -118,6 +118,8 @@ std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& i
return in;
}
BOOST_PFR_BEGIN_MODULE_EXPORT
template <class Char, class Traits, class T>
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, io_fields_impl<const T&>&& ) {
static_assert(sizeof(T) && false, "====================> Boost.PFR: Attempt to use istream operator on a boost::pfr::io_fields wrapped type T with const qualifier.");
@@ -130,8 +132,12 @@ std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& i
return in;
}
BOOST_PFR_END_MODULE_EXPORT
} // namespace detail
BOOST_PFR_BEGIN_MODULE_EXPORT
/// IO manipulator to read/write \aggregate `value` field-by-field.
///
/// \b Example:
@@ -159,6 +165,8 @@ auto io_fields(T&& value) noexcept {
return detail::io_fields_impl<T>{std::forward<T>(value)};
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_IO_FIELDS_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -77,6 +77,7 @@ namespace detail {
>;
} // namespace detail
BOOST_PFR_BEGIN_MODULE_EXPORT
/// \brief Compares lhs and rhs for equality using their own comparison and conversion operators; if no operators available returns \forcedlink{eq_fields}(lhs, rhs).
///
@@ -182,6 +183,8 @@ constexpr detail::enable_hashable_t<T> hash_value(const T& value) {
return std::hash<T>{}(value);
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_OPS_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -33,6 +33,8 @@
/// \b Synopsis:
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
/// Does a field-by-field equality comparison.
///
/// \returns `L == R && tuple_size_v<T> == tuple_size_v<U>`, where `L` and
@@ -122,6 +124,9 @@ namespace boost { namespace pfr {
return result;
#endif
}
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_OPS_HPP

View File

@@ -19,6 +19,8 @@
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
/// Has a static const member variable `value` when it is known that type T can or can't be reflected using Boost.PFR; otherwise, there is no member variable.
/// Every user may (and in some difficult cases - should) specialize is_reflectable on his own.
///
@@ -54,6 +56,8 @@ using is_implicitly_reflectable = std::integral_constant< bool, boost::pfr::deta
template<class T, class WhatFor>
constexpr bool is_implicitly_reflectable_v = is_implicitly_reflectable<T, WhatFor>::value;
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_TRAITS_HPP

View File

@@ -11,9 +11,13 @@
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
template<class T, class WhatFor>
struct is_reflectable;
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_DETAIL_TRAITS_FWD_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)
@@ -22,6 +22,8 @@
/// \b Synopsis:
namespace boost { namespace pfr {
BOOST_PFR_BEGIN_MODULE_EXPORT
/// Has a static const member variable `value` that contains fields count in a T.
/// Works for any T that satisfies \aggregate.
///
@@ -43,6 +45,8 @@ using tuple_size = detail::size_t_< boost::pfr::detail::fields_count<T>() >;
template <class T>
constexpr std::size_t tuple_size_v = tuple_size<T>::value;
BOOST_PFR_END_MODULE_EXPORT
}} // namespace boost::pfr
#endif // BOOST_PFR_TUPLE_SIZE_HPP

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html>
<!--
Copyright (c) 2014-2023 Antony Polukhin
Copyright (c) 2014-2024 Antony Polukhin
antoshkka at gmail dot com
Distributed under the Boost Software License,
@@ -31,7 +31,7 @@ boost-no-inspect
<a href="../../doc/html/boost_pfr.html">../../doc/html/boost_pfr.html</a>
</p>
<p>
&copy; 2014-2023 Antony Polukhin
&copy; 2014-2024 Antony Polukhin
</p>
</body>
</html>

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
# Copyright (c) 2016-2023 Antony Polukhin
# Copyright (c) 2016-2024 Antony Polukhin
# Copyright (c) 2023 Denis Mikhailov
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -15,7 +15,7 @@ import string
ascii_letters = string.ascii_letters.replace("o", "").replace("O", "").replace("i", "").replace("I", "").replace("T", "")
WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE = 3
PROLOGUE = """// Copyright (c) 2016-2023 Antony Polukhin
PROLOGUE = """// Copyright (c) 2016-2024 Antony Polukhin
// Copyright (c) 2023 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -38,7 +38,12 @@ PROLOGUE = """// Copyright (c) 2016-2023 Antony Polukhin
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/size_t_.hpp>
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#else
#include <type_traits> // for std::conditional_t, std::is_reference
#endif
namespace boost { namespace pfr { namespace detail {
@@ -134,7 +139,7 @@ class EmptyLinePrinter:
indexes = " a"
print(PROLOGUE)
funcs_count = 100 if len(sys.argv) == 1 else int(sys.argv[1])
funcs_count = 200 if len(sys.argv) == 1 else int(sys.argv[1])
max_args_on_a_line = len(ascii_letters)
for i in range(1, funcs_count):
if i % max_args_on_a_line == 0:

37
module/CMakeLists.txt Normal file
View File

@@ -0,0 +1,37 @@
# Copyright (c) 2016-2024 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.28)
function (_add_boost_pfr_module_impl NAME)
add_library(${NAME})
target_compile_features(${NAME} PUBLIC cxx_std_20)
target_sources(${NAME} PUBLIC
FILE_SET modules_public TYPE CXX_MODULES FILES
${CMAKE_CURRENT_LIST_DIR}/pfr.cppm
)
endfunction()
function (add_boost_pfr_module NAME)
_add_boost_pfr_module_impl(${NAME})
target_include_directories(${NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../include)
_add_boost_pfr_module_impl(${NAME}_migration)
target_include_directories(${NAME}_migration PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../include)
target_compile_definitions(${NAME}_migration PRIVATE BOOST_PFR_ATTACH_TO_GLOBAL_MODULE)
endfunction()
add_boost_pfr_module(boost_pfr_module)
add_library(Boost::pfr_module ALIAS boost_pfr_module)
add_library(Boost::pfr_module_migration ALIAS boost_pfr_module_migration)
if (BUILD_TESTING)
add_executable(boost_pfr_module_usage usage_sample.cpp)
target_link_libraries(boost_pfr_module_usage PRIVATE Boost::pfr_module)
# Make sure that mixing includes and imports is fine for different TU
add_executable(boost_pfr_module_usage_mu usage_test_mu1.cpp usage_test_mu2.cpp)
target_link_libraries(boost_pfr_module_usage_mu PRIVATE Boost::pfr_module_migration)
endif()

44
module/pfr.cppm Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (c) 2016-2024 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)
// To compile manually use a command like the folowing:
// clang++ -I ../include -std=c++20 --precompile -x c++-module pfr.cppm
#define BOOST_PFR_BEGIN_MODULE_EXPORT export {
#define BOOST_PFR_END_MODULE_EXPORT }
#ifndef BOOST_PFR_HAS_STD_MODULE
module;
#include <array>
#include <cstddef>
#include <functional>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#endif
export module Boost.PFR;
#ifdef BOOST_PFR_HAS_STD_MODULE
import std;
#endif
#ifdef __clang__
# pragma clang diagnostic ignored "-Winclude-angled-in-module-purview"
#endif
#ifdef BOOST_PFR_ATTACH_TO_GLOBAL_MODULE
extern "C++" {
#include <boost/pfr.hpp>
}
#else
#include <boost/pfr.hpp>
#endif

31
module/usage_sample.cpp Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2016-2024 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)
// To compile manually use a command like the folowing:
// clang++ -std=c++20 -fmodule-file=pfr.pcm pfr.pcm usage_sample.cpp
//[pfr_module_example
#include <iostream>
#include <iomanip>
#include <string>
import Boost.PFR;
struct some_person {
std::string name;
unsigned birth_year;
};
int main() {
some_person val{"Edgar Allan Poe", 1809};
std::cout << boost::pfr::get<0>(val) // No macro!
<< " was born in " << boost::pfr::get<1>(val); // Works with any aggregate!
std::cout << '\n' << boost::pfr::io(val); // Outputs: {"Edgar Allan Poe", 1809}
std::cout << "\n." << boost::pfr::get_name<0, some_person>()
<< '=' << val.name << '\n'; // Outputs: .name=Edgar Allan Poe
}
//]

27
module/usage_test_mu1.cpp Normal file
View File

@@ -0,0 +1,27 @@
// Copyright (c) 2016-2024 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)
// To compile manually use a command like the folowing:
// clang++ -std=c++20 -fmodule-file=pfr.pcm pfr.pcm usage_sample.cpp
#include <iostream>
#include <boost/pfr.hpp>
struct some_person {
std::string name;
unsigned birth_year;
};
void mu1_act() {
some_person val{"Edgar Allan Poe", 1809};
std::cout << boost::pfr::get<0>(val) // No macro!
<< " was born in " << boost::pfr::get<1>(val); // Works with any aggregate!
std::cout << '\n' << boost::pfr::io(val); // Outputs: {"Edgar Allan Poe", 1809}
std::cout << "\n." << boost::pfr::get_name<0, some_person>()
<< '=' << val.name << '\n'; // Outputs: .name=Edgar Allan Poe
}

32
module/usage_test_mu2.cpp Normal file
View File

@@ -0,0 +1,32 @@
// Copyright (c) 2016-2024 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)
// To compile manually use a command like the folowing:
// clang++ -std=c++20 -fmodule-file=pfr.pcm pfr.pcm usage_sample.cpp
#include <iostream>
#include <iomanip>
import Boost.PFR;
struct some_person {
std::string name;
unsigned birth_year;
};
void mu1_act();
int main() {
mu1_act();
some_person val{"Joseph Brodsky", 1940};
std::cout << boost::pfr::get<0>(val) // No macro!
<< " was born in " << boost::pfr::get<1>(val); // Works with any aggregate!
std::cout << '\n' << boost::pfr::io(val);
std::cout << "\n." << boost::pfr::get_name<0, some_person>()
<< '=' << val.name << '\n';
}

View File

@@ -5,13 +5,17 @@
# http://www.boost.org/LICENSE_1_0.txt)
#
import-search /boost/config/checks ;
import python ;
import testing ;
import ../../config/checks/config : requires ;
import config : requires ;
project
: source-location .
: requirements
<library>/boost/config//boost_config
<library>/boost/preprocessor//boost_preprocessor
<define>BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING=1
;

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,17 +1,24 @@
# Copyright (C) 2016-2023 Antony Polukhin.
# Copyright (C) 2016-2024 Antony Polukhin.
#
# Use, modification and distribution is subject to 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)
#
import-search /boost/config/checks ;
import python ;
import testing ;
import ../../config/checks/config : requires ;
import config : requires ;
project
: source-location .
: requirements
<library>/boost/config//boost_config
<library>/boost/core//boost_core
<library>/boost/container_hash//boost_container_hash
<library>/boost/type_index//boost_type_index
<define>BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING=1
[ requires cxx14_constexpr ]
;
@@ -63,6 +70,10 @@ test-suite pfr_tests
[ run ../../example/sample_printing.cpp : : : : auto_engine_sample_printing ]
[ run ../../example/get.cpp : : : : auto_engine_get ]
[ run ../../example/quick_examples.cpp : : : : auto_engine_quick ]
[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON=void : fields_count_on_incomplete_type_void ]
[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON="void()" : fields_count_on_incomplete_type_function ]
[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON="struct Foo" : fields_count_on_incomplete_type_struct ]
;
local BLACKLIST_TESTS_FOR_LOOPHOLE =
@@ -73,7 +84,7 @@ local BLACKLIST_TESTS_FOR_LOOPHOLE =
tie_anonymous_const_field # boost::pfr::structure_tie gives compile time error on const fields
;
# Those tests are either
# Those tests are either
# * reflecting a non literal type
# * or calling boost::pfr::get and the result is a user defined structure
local BLACKLIST_TESTS_FOR_CLASSIC =
@@ -99,7 +110,7 @@ for local source_file in [ glob ./run/*.cpp ] [ glob ../../example/*.cpp ]
{
local target_name = $(source_file[1]:B) ;
pfr_tests += [ run $(source_file) : : : $(STRUCTURED_BINDING_ENGINE) : $(target_name)_sb ] ;
if ! $(target_name) in $(BLACKLIST_TESTS_FOR_LOOPHOLE)
{
pfr_tests += [ run $(source_file) : : : $(LOOPHOLE_ENGINE) : $(target_name)_lh ] ;

View File

@@ -0,0 +1,15 @@
// Copyright (c) 2023-2024 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/tuple_size.hpp>
struct A {
template <typename... Args>
explicit A(Args&&...) {}
};
int main() {
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error
}

View File

@@ -0,0 +1,15 @@
// Copyright (c) 2023-2024 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/tuple_size.hpp>
struct A {
template <typename Arg0, typename... Args>
explicit A(Arg0&&, Args&&...) {}
};
int main() {
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 Antony Polukhin
// Copyright (c) 2020 Richard Hodges
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -0,0 +1,10 @@
// Copyright (c) 2023-2024 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/detail/fields_count.hpp>
int main() {
return static_cast<int>(boost::pfr::detail::fields_count<BOOST_PFR_RUN_TEST_ON>());
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2019 Ilya Kiselev
// Copyright (c) 2019-2023 Antony Polukhin
// Copyright (c) 2019-2024 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)

View File

@@ -1,21 +1,86 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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/tuple_size.hpp>
struct bf {
unsigned int i1: 1;
unsigned int i2: 1;
unsigned int i3: 1;
unsigned int i4: 1;
unsigned int i5: 1;
unsigned int i6: 1;
#include <cstdint>
struct bf7 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
};
static_assert(sizeof(bf7) == 1, "");
struct bf8 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
};
static_assert(sizeof(bf8) == 1, "");
struct bf16 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t b8 : 1;
uint8_t b9 : 1;
uint8_t b10 : 1;
uint8_t b11 : 1;
uint8_t b12 : 1;
uint8_t b13 : 1;
uint8_t b14 : 1;
uint8_t b15 : 1;
};
static_assert(sizeof(bf16) == 2, "");
struct bf24 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t b8 : 1;
uint8_t b9 : 1;
uint8_t b10 : 1;
uint8_t b11 : 1;
uint8_t b12 : 1;
uint8_t b13 : 1;
uint8_t b14 : 1;
uint8_t b15 : 1;
uint8_t b16 : 1;
uint8_t b17 : 1;
uint8_t b18 : 1;
uint8_t b19 : 1;
uint8_t b20 : 1;
uint8_t b21 : 1;
uint8_t b22 : 1;
uint8_t b23 : 1;
};
static_assert(sizeof(bf24) == 3, "");
int main() {
static_assert(boost::pfr::tuple_size<bf>::value == 6, "");
static_assert(boost::pfr::tuple_size_v<bf7> == 7, "");
static_assert(boost::pfr::tuple_size_v<bf8> == 8, "");
static_assert(boost::pfr::tuple_size_v<bf16> == 16, "");
static_assert(boost::pfr::tuple_size_v<bf24> == 24, "");
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2018 Adam Butcher, Antony Polukhin
// Copyright (c) 2019-2023 Antony Polukhin
// Copyright (c) 2019-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2024 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/tuple_size.hpp>
#include <climits>
#include <cstdint>
#if defined(__clang__)
# if SIZE_MAX > (1ULL << 32) - 1
# define ARRAY_MAX (SIZE_MAX >> 3)
# else
# define ARRAY_MAX SIZE_MAX
# endif
# define OBJECT_MAX SIZE_MAX
#elif defined(__GNUC__)
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX (SIZE_MAX >> 1)
#elif defined(_MSC_VER)
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX UINT_MAX
#else // Let's play it safe
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX INT_MAX
#endif
#pragma pack(1)
struct A {
char x[ARRAY_MAX <= (OBJECT_MAX >> 3) ? ARRAY_MAX : OBJECT_MAX >> 3];
};
struct B {
A a;
A b;
A c;
A d;
A e;
A f;
A g;
A h;
};
struct C {
A& a;
A b;
A c;
A d;
A e;
A f;
A g;
A h;
};
#pragma pack()
int main() {
#ifndef _MSC_VER
static_assert(boost::pfr::tuple_size_v<char[ARRAY_MAX]> == ARRAY_MAX, "");
#endif
static_assert(boost::pfr::tuple_size_v<B> == 8, "");
static_assert(boost::pfr::tuple_size_v<C> == 8, "");
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)
@@ -22,7 +22,7 @@ int main() {
#if BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
// MSVC-14.3 fails this test
#if !defined(_MSC_VER) || _MSC_VER < 1930 || _MSC_VER > 1939
#if !defined(_MSC_VER) || _MSC_VER < 1930 || _MSC_VER > 1949
static_assert(boost::pfr::tuple_size_v<S> == 4, "");
struct S5_0 { int x0; int x1; int x2; int x3; X x4; };

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023 Antony Polukhin
// Copyright (c) 2018-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023 Antony Polukhin
// Copyright (c) 2020-2024 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)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2016-2024 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)

Some files were not shown because too many files have changed in this diff Show More