mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-22 05:22:32 +00:00
Compare commits
28 Commits
2.2.0
...
boost-1.87
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f09e6aeae9 | ||
|
|
69263f4757 | ||
|
|
469ac134f3 | ||
|
|
ff415a26ff | ||
|
|
8cd1a9675d | ||
|
|
4d912c1925 | ||
|
|
e1a0832a0e | ||
|
|
73938e0936 | ||
|
|
e4cbbc78f0 | ||
|
|
6591a8609d | ||
|
|
3d090e7c6f | ||
|
|
e1e908e804 | ||
|
|
60391652fa | ||
|
|
dec9341546 | ||
|
|
449bf360f7 | ||
|
|
5f857d5503 | ||
|
|
9b90f2f6bb | ||
|
|
8f3b819b1e | ||
|
|
4a973c5eb4 | ||
|
|
4c15f217f4 | ||
|
|
e969c57be5 | ||
|
|
16d771f498 | ||
|
|
16a97bb1f5 | ||
|
|
8a0447b486 | ||
|
|
b674d728be | ||
|
|
5b55480c65 | ||
|
|
98789f610a | ||
|
|
c695aa0b32 |
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
@@ -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
20
build.jam
Normal 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
|
||||
;
|
||||
|
||||
@@ -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"
|
||||
|
||||
58
doc/pfr.qbk
58
doc/pfr.qbk
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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."
|
||||
);
|
||||
|
||||
|
||||
50
include/boost/pfr/detail/for_each_field.hpp
Normal file
50
include/boost/pfr/detail/for_each_field.hpp
Normal 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
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
|
||||
@@ -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))>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
© 2014-2023 Antony Polukhin
|
||||
© 2014-2024 Antony Polukhin
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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
37
module/CMakeLists.txt
Normal 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
44
module/pfr.cppm
Normal 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
31
module/usage_sample.cpp
Normal 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
27
module/usage_test_mu1.cpp
Normal 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
32
module/usage_test_mu2.cpp
Normal 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';
|
||||
}
|
||||
@@ -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
|
||||
;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ] ;
|
||||
|
||||
15
test/core/compile-fail/constructible_0_or_more_args.cpp
Normal file
15
test/core/compile-fail/constructible_0_or_more_args.cpp
Normal 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
|
||||
}
|
||||
15
test/core/compile-fail/constructible_1_or_more_args.cpp
Normal file
15
test/core/compile-fail/constructible_1_or_more_args.cpp
Normal 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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
10
test/core/fields_count_on_incomplete_type.cpp
Normal file
10
test/core/fields_count_on_incomplete_type.cpp
Normal 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>());
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
63
test/core/run/huge_count.cpp
Normal file
63
test/core/run/huge_count.cpp
Normal 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, "");
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
1019
test/core/run/many_fields_count.cpp
Normal file
1019
test/core/run/many_fields_count.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; };
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user