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

Compare commits

..

4 Commits

Author SHA1 Message Date
Antony Polukhin
442928eeb4 fixes 2023-02-14 09:23:15 +03:00
Antony Polukhin
d4095b3fbd update the generation script 2023-02-12 19:46:27 +03:00
Antony Polukhin
19d5a1d0e6 test fixes 2023-02-12 19:39:49 +03:00
Antony Polukhin
e002e42910 make the result type of boost::pfr::get exactly match std::get 2023-02-11 21:52:40 +03:00
121 changed files with 632 additions and 2500 deletions

View File

@@ -17,41 +17,30 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: gcc-13
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
- toolset: gcc-12 # Do not remove! It is the only toolset that tests misc/strip_boost_namespace.sh
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
- toolset: gcc-9 # 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
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-12"
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-11"
os: ubuntu-18.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
os: ubuntu-18.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-10"
- toolset: gcc-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-22.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-9"
- toolset: clang-15
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
# - toolset: clang
# cxxstd: "03,11,14,17,2a"
# os: macos-10.15
# cxxflags: "cxxflags=-fsanitize=address,undefined -fno-sanitize-recover=undefined"
# linkflags: "linkflags=-fsanitize=address,undefined"
os: ubuntu-20.04
cxxflags: "cxxflags=-fsanitize=address,undefined,integer -fno-sanitize-recover=undefined"
linkflags: "linkflags=-fsanitize=address,undefined,integer"
# To low quota to use
#- toolset: clang
# cxxstd: "03,11,14,17,2a"
# os: macos-10.15
# cxxflags: "cxxflags=-fsanitize=address,undefined -fno-sanitize-recover=undefined"
# linkflags: "linkflags=-fsanitize=address,undefined"
runs-on: ${{matrix.os}}
@@ -87,6 +76,11 @@ jobs:
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build
- name: Create user-config.jam
if: matrix.compiler
run: |
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
- name: Run tests
run: |
cd ../boost-root
@@ -94,7 +88,7 @@ jobs:
dist/bin/inspect libs/$LIBRARY
- name: Test boost namespace stripping
if: ${{matrix.toolset == 'gcc-12'}}
if: ${{matrix.toolset == 'gcc-9'}}
run: ../boost-root/libs/$LIBRARY/misc/strip_boost_namespace.sh
- name: Prepare coverage data
@@ -104,9 +98,9 @@ jobs:
echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
wget https://github.com/linux-test-project/lcov/archive/v1.16.zip
unzip v1.16.zip
LCOV="`pwd`/lcov-1.16/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh"
wget https://github.com/linux-test-project/lcov/archive/v1.15.zip
unzip v1.15.zip
LCOV="`pwd`/lcov-1.15/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh"
echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info"
$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info
@@ -130,25 +124,20 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: msvc-14.0
cxxstd: "14,latest"
addrmd: 32,64
os: windows-2019
threads: "-j3"
# TODO: fails the loophole tests
#- toolset: msvc
# cxxstd: "14,17,latest"
# addrmd: 32,64
# os: windows-2022
# TODO: fails the loophole tests
#- toolset: msvc-14.2
# cxxstd: "14,17,latest"
# addrmd: 32,64
# os: windows-2019
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
threads: "-j3"
- toolset: msvc-14.3
cxxstd: "20,latest"
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}}
@@ -181,7 +170,7 @@ jobs:
shell: cmd
run: |
cd ../boost-root
b2 ${{matrix.threads}} libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
finish:
needs: posix

View File

@@ -45,8 +45,6 @@ Outputs:
Edgar Allan Poe was born in 1809
```
[Run the above sample](https://godbolt.org/z/PfYsWKb7v)
### Motivating Example #1
```c++

View File

@@ -32,12 +32,9 @@ local doxygen_params =
<doxygen:param>"ALIASES= \\
\"forcedlink{1}=\\xmlonly<link linkend='boost.pfr.\\1'>\\endxmlonly boost::pfr::\\1\\xmlonly</link>\\endxmlonly\" \\
\"podops=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.three_ways_of_getting_operators'>\\endxmlonly 'Three ways of getting operators' \\xmlonly</link>\\endxmlonly\" \\
\"fnrefl=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.reflection_of_field_name'>\\endxmlonly 'Reflection of field names' \\xmlonly</link>\\endxmlonly\" \\
\"customio=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.custom_printing_of_aggregates'>\\endxmlonly 'Custom printing of aggregates' \\xmlonly</link>\\endxmlonly for info on how to implement your own manipulator with custom format.\" \\
\"aggregate=\\xmlonly<link linkend='boost_pfr.limitations_and_configuration'>\\endxmlonly simple aggregate \\xmlonly</link>\\endxmlonly\" \\
"
<doxygen:param>"PREDEFINED= \\
\"BOOST_PFR_DOXYGEN_INVOKED=1\" \\
\"BOOST_PFR_DOXYGEN_INVOKED\" \\
"
;
@@ -47,7 +44,7 @@ doxygen autodoc_pfr
[ glob ../../../boost/pfr/*.hpp ]
:
$(doxygen_params)
<xsl:param>"boost.doxygen.reftitle=Reference Section of PFR"
<xsl:param>"boost.doxygen.reftitle=Reference Section"
;
boostbook pfr-doc
@@ -55,7 +52,7 @@ boostbook pfr-doc
pfr.qbk
:
<dependency>autodoc_pfr
<xsl:param>boost.root=https://www.boost.org/doc/libs/1_81_0
<xsl:param>boost.root=https://www.boost.org/doc/libs/1_72_0
#<xsl:param>boost.root=../../../.
<xml:param>html.stylesheet=../../../../doc/src/boostbook.css
;

View File

@@ -1,7 +1,7 @@
[library Boost.PFR
[quickbook 1.6]
[version 2.2]
[copyright 2016-2024 Antony Polukhin]
[version 2.0]
[copyright 2016-2023 Antony Polukhin]
[category Language Features Emulation]
[license
Distributed under the Boost Software License, Version 1.0.
@@ -17,7 +17,6 @@ Boost.PFR is a C++14 library for a very basic reflection. It gives you access to
[import ../example/motivating_example0.cpp]
[pfr_motivating_example]
Experiment with the sample [@https://godbolt.org/z/PfYsWKb7v online].
See [link boost_pfr.limitations_and_configuration [*limitations]].
@@ -43,20 +42,20 @@ user_info retrieve_friend(std::string_view name) {
name
);
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
user_info info {
std::move(std::get<0>(info_tuple)),
std::move(std::get<1>(info_tuple)),
std::move(std::get<2>(info_tuple)),
std::move(std::get<3>(info_tuple)),
}
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
auto friend_info = ask_user_for_friend(std::move(info));
db::insert(
"INSERT INTO user_infos(id, name, email, login) VALUES ($0, $1, $2, $3)",
friend_info.id, //////////////////////////////////////////////////////
friend_info.id, /////////////////////////////////////////////////////////
friend_info.name, // Users are forced to enumerate fields because your
friend_info.email, // library can not iterate over the fields of a user
friend_info.login // provided structure
@@ -81,20 +80,20 @@ user_info retrieve_friend(std::string_view name) {
name
);
////////////////// No boilerplate code to move data around //////////////////
////////////////// No boilerplate code to move data around /////////////////////
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
auto friend_info = ask_user_for_friend(std::move(info));
db::insert(
"INSERT INTO user_infos(id, name, email, login) VALUES ($0, $1, $2, $3)",
friend_info /////////////////////////////////////////////////////////
friend_info ////////////////////////////////////////////////////////////
// Boost.PFR allows you to iterate over all the fields
// of a user provided structure
//
@@ -120,7 +119,7 @@ struct user_info {
std::string name, email, login;
};
/// Customizations via hand-written code ////////////////////////////////////////
/// Customizations via hand-written code or macro like BOOST_FUSION_ADAPT_STRUCT ///
auto db_api_tie(user_info& ui) noexcept {
return std::tie(ui.id, ui.name, ui.email, ui.login);
}
@@ -128,7 +127,7 @@ auto db_api_tie(user_info& ui) noexcept {
auto db_api_tie(const user_info& ui) noexcept {
return std::tie(ui.id, ui.name, ui.email, ui.login);
}
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
```
][
```
@@ -139,7 +138,7 @@ struct user_info {
std::string name, email, login;
};
//////// With Boost.PFR there's no need in hand written customizations //////////
//////// With Boost.PFR there's no need in hand written customizations /////////////
@@ -147,29 +146,14 @@ struct user_info {
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
```
]]
]
Imagine that you are writing a serialization library. Serialization of user
provided structures (and nested structures) with Boost.PFR it is just as simple as:
```
void Write(Writer& writer, int value);
void Write(Writer& writer, std::string_view value);
template <typename T>
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); });
}
```
With Boost.PFR the code is shorter, more readable and more pleasant to write.
[note All the above examples were inspired by the Boost.PFR usage in [@https://github.com/userver-framework/userver 🐙 userver framework].]
[h2 Out of the box functionality ]
@@ -180,17 +164,15 @@ Boost.PFR adds the following out-of-the-box functionality for aggregate initiali
* heterogeneous comparators
* hash
* IO streaming
* access to members by index or type
* access to member's names by index
* access to members by index
* member type retrieval
* methods for cooperation with `std::tuple` for members
* methods for cooperation with `std::array` for member's names
* methods for cooperation with `std::tuple`
* methods to visit each field of the structure
* trait to detect potential ability to reflect type, and ability to override trait's decision in user-side code
Boost.PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder [@https://github.com/boostorg/pfr from the Boost.PFR github] into your project, and the library will work fine. For a version of the library without `boost::` namespace see [@https://github.com/apolukhin/pfr_non_boost PFR].
[caution Recommended C++ Standards are C++20 and above. C++17 completely enough for a user who doesn't want accessing name of structure member. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
[caution Recommended C++ Standards are C++17 and above. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
[endsect]
@@ -205,9 +187,6 @@ Boost.PFR is a header only library that does not depend on Boost. You can just c
[
[ [pfr_quick_examples_get] ]
[ [funcref boost::pfr::get] ]
][
[ [pfr_quick_examples_get_name] ]
[ [funcref boost::pfr::get_name] ]
][
[ [pfr_quick_examples_ops] ]
[
@@ -274,7 +253,6 @@ Boost.PFR is a header only library that does not depend on Boost. You can just c
[import ../example/sample_printing.cpp]
[import ../example/get.cpp]
[import ../example/get_name.cpp]
[section Why tuples are bad and aggregates are more preferable?]
@@ -454,21 +432,12 @@ error: static_assert failed "====================> Boost.PFR: For safety reasons
[endsect]
[section Reflection of field name ]
[pfr_example_get_name]
See [link boost_pfr.limitations_and_configuration [*Limitations and Configuration]].
[endsect]
[endsect]
[section Limitations and Configuration]
[caution Recommended C++ Standards are C++20 and above. C++17 completely enough for a user who doesn't want accessing name of structure member. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported. ]
[caution Recommended C++ Standards are C++17 and above. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported. ]
Boost.PFR library works with types that satisfy the requirements of `SimpleAggregate`: aggregate types without base classes, `const` fields, references, or C arrays:
@@ -490,9 +459,6 @@ 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 only `SimpleAggregate` types.
[h2 Configuration Macro]
By default Boost.PFR [*auto-detects your compiler abilities] and automatically defines the configuration macro into appropriate values. If you wish to override that behavior, just define:
@@ -503,9 +469,6 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d
[[*BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE*] [Define to `0` if you are hit by the template instantiation depth issues with `std::make_integer_sequence` and wish to use Boost.PFR version of that metafunction. Define to `1` to override Boost.PFR detection logic. ]]
[[*BOOST_PFR_HAS_GUARANTEED_COPY_ELISION*] [Define to `0` if your compiler does not implement C++17 guaranteed copy elision properly and fails to reflect aggregates with non-movable fields. Define to `1` to override Boost.PFR detection logic. ]]
[[*BOOST_PFR_ENABLE_IMPLICIT_REFLECTION*] [Define to `0` if you are hit by lots of non-effective choices made by implicitly reflection. Define to `1` to override Boost.PFR detection logic. ]]
[[*BOOST_PFR_CORE_NAME_ENABLED*] [On platforms where field name extraction is not supported, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_CORE_NAME_ENABLED macro equal to 0. Defining this macro as 0 before including the header disables the ability to get a field name. ]]
[[*BOOST_PFR_FUNCTION_SIGNATURE*] [For known compilers defined to a compiler specific macro, that outputs the whole function signature including non-type template parameters. ]]
[[*BOOST_PFR_CORE_NAME_PARSING*] [Describes extraction of field name from BOOST_PFR_FUNCTION_SIGNATURE macro. See details below. ]]
[[*BOOST_PFR_ENABLED*] [On platforms where Boost.PFR is not supported, the `boost/pfr/config.hpp` header defines the BOOST_PFR_ENABLED macro equal to 0. Defining this macro as 0 before including the header disables the Boost.PFR library. ]]
]
@@ -523,36 +486,11 @@ The Boost.PFRs reflection has some limitations that depend on a C++ Standard and
* T must be constexpr aggregate initializable and all its fields must be constexpr default constructible
* [funcref boost::pfr::get], [funcref boost::pfr::structure_to_tuple], [funcref boost::pfr::structure_tie], [headerref boost/pfr/core.hpp boost::pfr::tuple_element] require T to be a POD type with built-in types only.
The Boost.PFRs extraction of field name has some limitations that depend on a C++ Standard and compiler capabilities:
* T should be usable like `extern T t;`, i.e. has a non-internal linkage.
[h2 Adjusting BOOST_PFR_CORE_NAME_PARSING]
`BOOST_PFR_CORE_NAME_PARSING` is already set up for most of the popular compilers. You need to adjust it only
if some static_assert in the library complained on `BOOST_PFR_CORE_NAME_PARSING`.
To do that:
# Build `test/core_name/print_name.cpp` with your compiler and run it
# Define BOOST_PFR_CORE_NAME_PARSING to `(skip_at_begin, skip_at_end, "")`, where
* `skip_at_begin` is equal to characters count before the first occurrence of `user_defined_field` in output
* `skip_at_end` is equal to characters count after last occurrence of `user_defined_field` in output
# Check that `test/core_name/print_name.cpp` returns "user_defined_field"
# If it does not return `user_defined_field`, then define BOOST_PFR_CORE_NAME_PARSING to `(skip_at_begin, skip_at_end, "T = ")`, where
* `skip_at_begin` is equal to `skip_at_begin` at step 2
* `skip_at_end` is equal to `skip_at_end` at step 2
* `"T = "` is equal to characters that are right before the `user_defined_field` in output, use `backward("T = ")` to search for the occurange in the string from the right
# (optional, but highly recommended) [@https://github.com/boostorg/pfr/issues create ticket] with
feature request to add your compiler to supported compilers list. Include
parameters provided to `BOOST_PFR_CORE_NAME_PARSING` macro [*and] the initial output of `test/core_name/print_name.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,17 +517,6 @@ Long description of some basics: [@https://youtu.be/UlNUNxLtBI0 Antony Polukhin:
Long description of some basics of C++14 with [link boost_pfr.limitations_and_configuration [*BOOST_PFR_USE_LOOPHOLE == 0]]: [@https://youtu.be/abdeAew3gmQ Antony Polukhin: C++14 Reflections Without Macros, Markup nor External Tooling].
Description of the [*BOOST_PFR_USE_LOOPHOLE == 1] technique by its inventor Alexandr Poltavsky [@http://alexpolt.github.io/type-loophole.html in his blog].
[h2 Field name retrieval]
# at compile-time:
* Get references to members of an object of type `T` in `constexpr` function
* Feed the reference from previous as a template parameter to a `constexpr` function with `template <auto member_ptr>`.
That function returns `__PRETTY_FUNCTION__` or some other vendor specific macro that prints the whole name of a function
along with the template arguments.
* The returned value from previous step contains the member name ([@https://godbolt.org/z/K4aWdcE9G godbolt example]). Do some
compiler specific parsing of the value and make a `std::string_view` that contains only the member name.
# at run-time: return the `std::string_view` with the member name.
[endsect]
[section Acknowledgements]

View File

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

View File

@@ -1,43 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#include <boost/pfr/config.hpp>
#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17
//[pfr_example_get_name
/*`
Since C++20 it's possible to read name of a structure field by index using Boost.PFR library.
The following example shows how to do it using [funcref boost::pfr::get_name].
Let's define some structure:
*/
#include <boost/pfr/core_name.hpp>
struct foo { // defining structure
int some_integer;
char c;
};
/*`
We can access field's names of that structure by index:
*/
constexpr std::string_view n1 = boost::pfr::get_name<0, foo>(); // returns "some_integer"
constexpr std::string_view n2 = boost::pfr::get_name<1, foo>(); // returns "c"
//] [/pfr_example_get_name]
#endif
int main() {
#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17
if (n1 != "some_integer") return 1;
if (n2 != "c") return 2;
#endif
return 0;
}

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright 2016-2024 Antony Polukhin
// Copyright 2016-2023 Antony Polukhin
// Distributed under the Boost Software License, Version 1.0.
// (See the accompanying file LICENSE_1_0.txt
@@ -91,7 +91,7 @@ void test_examples() {
{
//[pfr_quick_examples_get
// Get field by index/type and assign new value to that field
// Get field by index and assign new value to that field
struct sample {
char c;
@@ -100,33 +100,11 @@ void test_examples() {
sample var{};
boost::pfr::get<1>(var) = 42.01f;
boost::pfr::get<char>(var) = 'A';
std::cout << var.c << var.f; // Outputs: A 42.01
std::cout << var.f; // Outputs: 42.01
//]
}
// 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 f_int;
long f_long;
};
std::cout << boost::pfr::get_name<0, sample>()
<< boost::pfr::get_name<1, sample>(); // Outputs: f_int f_long
//]
}
#endif
#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
{
//[pfr_quick_examples_structure_to_tuple

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -11,7 +11,6 @@
#include <boost/pfr/config.hpp>
#include <boost/pfr/core.hpp>
#include <boost/pfr/core_name.hpp>
#include <boost/pfr/functions_for.hpp>
#include <boost/pfr/functors.hpp>
#include <boost/pfr/io.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2022 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -98,33 +98,6 @@
# endif
#endif
#ifndef BOOST_PFR_CORE_NAME_ENABLED
# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L))
# if (defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911) \
|| (defined(__clang_major__) && __clang_major__ >= 12)
# define BOOST_PFR_CORE_NAME_ENABLED 1
# else
# define BOOST_PFR_CORE_NAME_ENABLED 0
# endif
# else
# define BOOST_PFR_CORE_NAME_ENABLED 0
# endif
#endif
#ifndef BOOST_PFR_CORE_NAME_PARSING
# 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("."))
# elif defined(__GNUC__)
# define BOOST_PFR_CORE_NAME_PARSING (sizeof("consteval auto boost::pfr::detail::name_of_field_impl() [with MsvcWorkaround = ") - 1, sizeof(")]") - 1, backward("::"))
# else
// Default parser for other platforms... Just skip nothing!
# define BOOST_PFR_CORE_NAME_PARSING (0, 0, "")
# endif
#endif
#if defined(__has_cpp_attribute)
# if __has_cpp_attribute(maybe_unused)
# define BOOST_PFR_MAYBE_UNUSED [[maybe_unused]]

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -30,25 +30,20 @@
namespace boost { namespace pfr {
/// \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`.
///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
/// my_struct s {10, 11};
///
/// assert(boost::pfr::get<0>(s) == 10);
/// boost::pfr::get<1>(s) = 0;
///
/// assert(boost::pfr::get<int>(s) == 10);
/// boost::pfr::get<short>(s) = 11;
/// \endcode
template <std::size_t I, class T>
constexpr decltype(auto) get(const T& val) noexcept {
return detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) );
}
/// \overload get
template <std::size_t I, class T>
constexpr decltype(auto) get(T& val
@@ -71,42 +66,8 @@ constexpr auto get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nul
/// \overload get
template <std::size_t I, class T>
constexpr auto get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
return std::move(detail::sequence_tuple::get<I>( detail::tie_as_tuple(val) ));
}
/// \overload get
template <class U, class T>
constexpr const U& get(const T& val) noexcept {
return detail::sequence_tuple::get_by_type_impl<const U&>( detail::tie_as_tuple(val) );
}
/// \overload get
template <class U, class T>
constexpr U& get(T& val
#if !BOOST_PFR_USE_CPP17
, std::enable_if_t<std::is_assignable<T, T>::value>* = nullptr
#endif
) noexcept {
return detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) );
}
#if !BOOST_PFR_USE_CPP17
/// \overload get
template <class U, class T>
constexpr U& get(T&, std::enable_if_t<!std::is_assignable<T, T>::value>* = nullptr) noexcept {
static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::get on non const non assignable type is allowed only in C++17");
return 0;
}
#endif
/// \overload get
template <class U, class T>
constexpr U&& get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
return std::move(detail::sequence_tuple::get_by_type_impl<U&>( detail::tie_as_tuple(val) ));
constexpr decltype(auto) get(T&& val, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
return detail::sequence_tuple::get<I>( detail::tie_as_tuple(std::forward<T>(val)) );
}
@@ -140,7 +101,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) {
constexpr auto structure_to_tuple(const T& val) noexcept {
return detail::make_stdtuple_from_tietuple(
detail::tie_as_tuple(val),
detail::make_index_sequence< tuple_size_v<T> >()
@@ -220,7 +181,7 @@ constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&
/// assert(sum == 42);
/// \endcode
template <class T, class F>
constexpr void for_each_field(T&& value, F&& func) {
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(

View File

@@ -1,88 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#ifndef BOOST_PFR_CORE_NAME_HPP
#define BOOST_PFR_CORE_NAME_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/core_name.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/stdarray.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <cstddef> // for std::size_t
#include <boost/pfr/tuple_size.hpp>
/// \file boost/pfr/core_name.hpp
/// Contains functions \forcedlink{get_name} and \forcedlink{names_as_array} to know which names each field of any \aggregate has.
///
/// \fnrefl for details.
///
/// \b Synopsis:
namespace boost { namespace pfr {
/// \brief Returns name of a field with index `I` in \aggregate `T`.
///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
///
/// assert(boost::pfr::get_name<0, my_struct>() == "i");
/// assert(boost::pfr::get_name<1, my_struct>() == "s");
/// \endcode
template <std::size_t I, class T>
constexpr
#ifdef BOOST_PFR_DOXYGEN_INVOKED
std::string_view
#else
auto
#endif
get_name() noexcept {
return detail::get_name<T, I>();
}
// FIXME: implement this
// template<class U, class T>
// constexpr auto get_name() noexcept {
// return detail::sequence_tuple::get_by_type_impl<U>( detail::tie_as_names_tuple<T>() );
// }
/// \brief Creates a `std::array` from names of fields of an \aggregate `T`.
///
/// \b Example:
/// \code
/// struct my_struct { int i, short s; };
/// std::array<std::string_view, 2> a = boost::pfr::names_as_array<my_struct>();
/// assert(a[0] == "i");
/// \endcode
template <class T>
constexpr
#ifdef BOOST_PFR_DOXYGEN_INVOKED
std::array<std::string_view, boost::pfr::tuple_size_v<T>>
#else
auto
#endif
names_as_array() noexcept {
return detail::make_stdarray_from_tietuple(
detail::tie_as_names_tuple<T>(),
detail::make_index_sequence< tuple_size_v<T> >(),
1L
);
}
}} // namespace boost::pfr
#endif // BOOST_PFR_CORE_NAME_HPP

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2016-2023 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP
#define BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <type_traits>
#include <utility> // metaprogramming stuff
#include <boost/pfr/detail/rvalue_t.hpp>
namespace boost { namespace pfr { namespace detail {
template <class T, class U>
constexpr void static_assert_layout_compatible() noexcept {
static_assert(
std::alignment_of<T>::value == std::alignment_of<U>::value,
"====================> Boost.PFR: Alignment check failed, probably your structure has user-defined alignment for the whole structure or for some of the fields."
);
static_assert(sizeof(T) == sizeof(U), "====================> Boost.PFR: Size check failed, probably your structure has bitfields or user-defined alignment.");
}
/// @cond
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
/// @endcond
template <class To, class From>
MAY_ALIAS const To& cast_to_layout_compatible(const From& val) noexcept {
MAY_ALIAS const To* const t = reinterpret_cast<const To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS const volatile To& cast_to_layout_compatible(const volatile From& val) noexcept {
MAY_ALIAS const volatile To* const t = reinterpret_cast<const volatile To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS volatile To& cast_to_layout_compatible(volatile From& val) noexcept {
MAY_ALIAS volatile To* const t = reinterpret_cast<volatile To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS To& cast_to_layout_compatible(From& val) noexcept {
MAY_ALIAS To* const t = reinterpret_cast<To*>( std::addressof(val) );
detail::static_assert_layout_compatible<To, From>();
return *t;
}
#ifdef BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING
template <class To, class From>
To&& cast_to_layout_compatible(rvalue_t<From> val) noexcept = delete;
#endif
#undef MAY_ALIAS
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -53,7 +53,7 @@ namespace typeid_conversions {
#ifdef _MSC_VER
# pragma warning( push )
// '<<': check operator precedence for possible error; use parentheses to clarify precedence
# pragma warning( disable : 4554 )
# pragma warning( disable : 4554 )
#endif
constexpr std::size_t native_types_mask = 31;
@@ -346,7 +346,7 @@ constexpr size_array<N> get_type_offsets() noexcept {
return offsets;
}
///////////////////// Returns array of typeids and zeros if constructor of a type accepts sizeof...(I) parameters
///////////////////// Returns array of typeids and zeros if construtor of a type accepts sizeof...(I) parameters
template <class T, std::size_t N, std::size_t... I>
constexpr void* flat_type_to_array_of_type_ids(std::size_t* types, std::index_sequence<I...>) noexcept
{

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2017-2018 Alexandr Poltavsky, Antony Polukhin.
// Copyright (c) 2019-2024 Antony Polukhin.
// Copyright (c) 2019-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)
@@ -8,7 +8,7 @@
// The Great Type Loophole (C++14)
// Initial implementation by Alexandr Poltavsky, http://alexpolt.github.io
//
// Description:
// Description:
// The Great Type Loophole is a technique that allows to exchange type information with template
// instantiations. Basically you can assign and read type information during compile time.
// Here it is used to detect data members of a data type. I described it for the first time in
@@ -27,6 +27,7 @@
#include <type_traits>
#include <utility>
#include <boost/pfr/detail/cast_to_layout_compatible.hpp> // still needed for enums
#include <boost/pfr/detail/offset_based_getter.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/make_flat_tuple_of_references.hpp>

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -52,12 +52,22 @@ constexpr auto tie_as_tuple(T& val) noexcept {
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
typedef size_t_<boost::pfr::detail::fields_count<T>()> fields_count_tag;
typedef size_t_<boost::pfr::detail::fields_count< T >()> fields_count_tag;
return boost::pfr::detail::tie_as_tuple(val, fields_count_tag{});
}
template <class T>
constexpr auto tie_as_tuple(T&& val) noexcept {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
typedef size_t_<boost::pfr::detail::fields_count< T >()> fields_count_tag;
return boost::pfr::detail::tie_as_tuple(std::forward<T>(val), fields_count_tag{});
}
template <class T, class F, std::size_t... I>
constexpr void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#ifndef BOOST_PFR_DETAIL_CORE_NAME_HPP
#define BOOST_PFR_DETAIL_CORE_NAME_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
// Each core_name provides `boost::pfr::detail::get_name` and
// `boost::pfr::detail::tie_as_names_tuple` functions.
//
// The whole functional of extracting field's names is build on top of those
// two functions.
#if BOOST_PFR_CORE_NAME_ENABLED
#include <boost/pfr/detail/core_name20_static.hpp>
#else
#include <boost/pfr/detail/core_name14_disabled.hpp>
#endif
#endif // BOOST_PFR_DETAIL_CORE_NAME_HPP

View File

@@ -1,43 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#ifndef BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP
#define BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
namespace boost { namespace pfr { namespace detail {
template <class T, std::size_t I>
constexpr auto get_name() noexcept {
static_assert(
sizeof(T) && false,
"====================> Boost.PFR: Field's names extracting functionality requires C++20."
);
return nullptr;
}
template <class T>
constexpr auto tie_as_names_tuple() noexcept {
static_assert(
sizeof(T) && false,
"====================> Boost.PFR: Field's names extracting functionality requires C++20."
);
return detail::sequence_tuple::make_sequence_tuple();
}
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP

View File

@@ -1,242 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#ifndef BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
#define BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
#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 <type_traits>
#include <string_view>
#include <array>
#include <memory> // for std::addressof
namespace boost { namespace pfr { namespace detail {
struct core_name_skip {
std::size_t size_at_begin;
std::size_t size_at_end;
bool is_backward;
std::string_view until_runtime;
consteval std::string_view apply(std::string_view sv) const noexcept {
// We use std::min here to make the compiler diagnostic shorter and
// cleaner in case of misconfigured BOOST_PFR_CORE_NAME_PARSING
sv.remove_prefix((std::min)(size_at_begin, sv.size()));
sv.remove_suffix((std::min)(size_at_end, sv.size()));
if (until_runtime.empty()) {
return sv;
}
const auto found = is_backward ? sv.rfind(until_runtime)
: sv.find(until_runtime);
const auto cut_until = found + until_runtime.size();
const auto safe_cut_until = (std::min)(cut_until, sv.size());
return sv.substr(safe_cut_until);
}
};
struct backward {
explicit consteval backward(std::string_view value) noexcept
: value(value)
{}
std::string_view value;
};
consteval core_name_skip make_core_name_skip(std::size_t size_at_begin,
std::size_t size_at_end,
std::string_view until_runtime) noexcept
{
return core_name_skip{size_at_begin, size_at_end, false, until_runtime};
}
consteval core_name_skip make_core_name_skip(std::size_t size_at_begin,
std::size_t size_at_end,
backward until_runtime) noexcept
{
return core_name_skip{size_at_begin, size_at_end, true, until_runtime.value};
}
// it might be compilation failed without this workaround sometimes
// See https://github.com/llvm/llvm-project/issues/41751 for details
template <class>
consteval std::string_view clang_workaround(std::string_view value) noexcept
{
return value;
}
template <class MsvcWorkaround, auto ptr>
consteval auto name_of_field_impl() noexcept {
// Some of the following compiler specific macro may be defined only
// inside the function body:
#ifndef BOOST_PFR_FUNCTION_SIGNATURE
# if defined(__FUNCSIG__)
# define BOOST_PFR_FUNCTION_SIGNATURE __FUNCSIG__
# elif defined(__PRETTY_FUNCTION__) || defined(__GNUC__) || defined(__clang__)
# define BOOST_PFR_FUNCTION_SIGNATURE __PRETTY_FUNCTION__
# else
# define BOOST_PFR_FUNCTION_SIGNATURE ""
# endif
#endif
constexpr std::string_view sv = detail::clang_workaround<MsvcWorkaround>(BOOST_PFR_FUNCTION_SIGNATURE);
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."
);
constexpr auto skip = detail::make_core_name_skip BOOST_PFR_CORE_NAME_PARSING;
static_assert(skip.size_at_begin + skip.size_at_end + skip.until_runtime.size() < sv.size(),
"====================> Boost.PFR: Field reflection parser configured in a wrong way. "
"It attempts to skip more chars than available. "
"Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
"'Limitations and Configuration' for more information."
);
constexpr auto fn = skip.apply(sv);
static_assert(
!fn.empty(),
"====================> Boost.PFR: Extraction of field name is misconfigured for your compiler. "
"It skipped all the input, leaving the field name empty. "
"Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
"'Limitations and Configuration' for more information."
);
auto res = std::array<char, fn.size()+1>{};
auto* out = res.data();
for (auto x: fn) {
*out = x;
++out;
}
return res;
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundefined-var-template"
// clang 16 and earlier don't support address of non-static member as template parameter
// but fortunately it's possible to use C++20 non-type template parameters in another way
// even in clang 16 and more older clangs
// all we need is to wrap pointer into 'clang_wrapper_t' and then pass it into template
template <class T>
struct clang_wrapper_t {
T v;
};
template <class T>
clang_wrapper_t(T) -> clang_wrapper_t<T>;
template <class T>
constexpr auto make_clang_wrapper(const T& arg) noexcept {
return clang_wrapper_t{arg};
}
#else
template <class T>
constexpr const T& make_clang_wrapper(const T& arg) noexcept {
// It's everything OK with address of non-static member as template parameter support on this compiler
// so we don't need a wrapper here, just pass the pointer into template
return arg;
}
#endif
template <class MsvcWorkaround, auto ptr>
consteval auto name_of_field() noexcept {
// Sanity check: known field name must match the deduced one
static_assert(
sizeof(MsvcWorkaround) // do not trigger if `name_of_field()` is not used
&& std::string_view{
detail::name_of_field_impl<
core_name_skip, detail::make_clang_wrapper(std::addressof(
detail::fake_object<core_name_skip>().size_at_begin
))
>().data()
} == "size_at_begin",
"====================> Boost.PFR: Extraction of field name is misconfigured for your compiler. "
"It does not return the proper field name. "
"Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See documentation section "
"'Limitations and Configuration' for more information."
);
return detail::name_of_field_impl<MsvcWorkaround, ptr>();
}
// Storing part of a string literal into an array minimizes the binary size.
//
// Without passing 'T' into 'name_of_field' different fields from different structures might have the same name!
// See https://developercommunity.visualstudio.com/t/__FUNCSIG__-outputs-wrong-value-with-C/10458554 for details
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>())
)))
>();
#ifdef __clang__
#pragma clang diagnostic pop
#endif
template <class T, std::size_t... I>
constexpr auto tie_as_names_tuple_impl(std::index_sequence<I...>) noexcept {
return detail::sequence_tuple::make_sequence_tuple(std::string_view{stored_name_of_field<T, I>.data()}...);
}
template <class T, std::size_t I>
constexpr std::string_view get_name() noexcept {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
static_assert(
!std::is_array<T>::value,
"====================> Boost.PFR: It is impossible to extract name from old C array since it doesn't have named members"
);
static_assert(
sizeof(T) && BOOST_PFR_USE_CPP17,
"====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
);
return stored_name_of_field<T, I>.data();
}
template <class T>
constexpr auto tie_as_names_tuple() noexcept {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
static_assert(
!std::is_array<T>::value,
"====================> Boost.PFR: It is impossible to extract name from old C array since it doesn't have named members"
);
static_assert(
sizeof(T) && BOOST_PFR_USE_CPP17,
"====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
);
return detail::tie_as_names_tuple_impl<T>(detail::make_index_sequence<detail::fields_count<T>()>{});
}
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP

View File

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

View File

@@ -1,57 +0,0 @@
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
//
// 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)
// Initial implementation by Bela Schaum, https://github.com/schaumb
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
//
#ifndef BOOST_PFR_DETAIL_FAKE_OBJECT_HPP
#define BOOST_PFR_DETAIL_FAKE_OBJECT_HPP
#pragma once
#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"
#elif defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC 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>
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 push
#elif defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
#endif // BOOST_PFR_DETAIL_FAKE_OBJECT_HPP

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -20,18 +20,18 @@ template <std::size_t Index>
using size_t_ = std::integral_constant<std::size_t, Index >;
template <class T, class F, class I, class = decltype(std::declval<F>()(std::declval<T>(), I{}))>
constexpr void for_each_field_impl_apply(T&& v, F&& f, I i, long) {
void for_each_field_impl_apply(T&& v, F&& f, I i, long) {
std::forward<F>(f)(std::forward<T>(v), i);
}
template <class T, class F, class I>
constexpr void for_each_field_impl_apply(T&& v, F&& f, I /*i*/, int) {
void for_each_field_impl_apply(T&& v, F&& f, I /*i*/, int) {
std::forward<F>(f)(std::forward<T>(v));
}
#if !defined(__cpp_fold_expressions) || __cpp_fold_expressions < 201603
template <class T, class F, std::size_t... I>
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
const int v[] = {0, (
detail::for_each_field_impl_apply(sequence_tuple::get<I>(t), std::forward<F>(f), size_t_<I>{}, 1L),
0
@@ -41,7 +41,7 @@ constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::
template <class T, class F, std::size_t... I>
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
const int v[] = {0, (
detail::for_each_field_impl_apply(sequence_tuple::get<I>(std::move(t)), std::forward<F>(f), size_t_<I>{}, 1L),
0
@@ -50,12 +50,12 @@ constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::
}
#else
template <class T, class F, std::size_t... I>
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(t), std::forward<F>(f), size_t_<I>{}, 1L), ...);
}
template <class T, class F, std::size_t... I>
constexpr void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(std::move(t)), std::forward<F>(f), size_t_<I>{}, 1L), ...);
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
// Copyright (c) 2017-2018 Chris Beck
// Copyright (c) 2019-2024 Antony Polukhin
// Copyright (c) 2019-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)
@@ -42,7 +42,7 @@ struct tuple_of_aligned_storage<sequence_tuple::tuple<Ts...>> {
using type = sequence_tuple::tuple<internal_aligned_storage<sizeof(Ts),
#if defined(__GNUC__) && __GNUC__ < 8 && !defined(__x86_64__) && !defined(__CYGWIN__)
// Before GCC-8 the `alignof` was returning the optimal alignment rather than the minimal one.
// We have to adjust the alignment because otherwise we get the wrong offset.
// We have to adjust the alignemnt because otherwise we get the wrong offset.
(alignof(Ts) > 4 ? 4 : alignof(Ts))
#else
alignof(Ts)

View File

@@ -20,8 +20,6 @@ constexpr decltype(is_reflectable<T, WhatFor>::value) possible_reflectable(long)
return is_reflectable<T, WhatFor>::value;
}
#if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
template <class T, class WhatFor>
constexpr bool possible_reflectable(int) noexcept {
# if defined(__cpp_lib_is_aggregate)
@@ -32,16 +30,6 @@ constexpr bool possible_reflectable(int) noexcept {
# endif
}
#else
template <class T, class WhatFor>
constexpr bool possible_reflectable(int) noexcept {
// negative answer here won't change behaviour in PFR-dependent libraries(like Fusion)
return false;
}
#endif
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_POSSIBLE_REFLECTABLE_HPP

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -39,7 +39,7 @@ struct tuple_base< std::index_sequence<I...>, Tail... >
constexpr tuple_base(const tuple_base&) = default;
constexpr tuple_base(Tail... v) noexcept
: base_from_member<I, Tail>{ v }...
: base_from_member<I, Tail>{ static_cast<Tail>(v) }...
{}
};
@@ -78,45 +78,12 @@ constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
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)
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)
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)
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)
return t.value;
}
template <class T, std::size_t N>
constexpr T&& get_by_type_impl(base_from_member<N, T>&& t) noexcept {
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)
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)
return std::forward<T>(t.value);
}
template <class ...Values>
struct tuple: tuple_base<
@@ -127,9 +94,6 @@ struct tuple: tuple_base<
detail::index_sequence_for<Values...>,
Values...
>::tuple_base;
constexpr static std::size_t size() noexcept { return sizeof...(Values); }
constexpr static bool empty() noexcept { return size() == 0; }
};
@@ -168,10 +132,6 @@ using tuple_element = std::remove_reference< decltype(
::boost::pfr::detail::sequence_tuple::get<I>( std::declval<T>() )
) >;
template <class... Args>
constexpr auto make_sequence_tuple(Args... args) noexcept {
return ::boost::pfr::detail::sequence_tuple::tuple<Args...>{ args... };
}
}}}} // namespace boost::pfr::detail::sequence_tuple

View File

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

View File

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

View File

@@ -1,41 +0,0 @@
// Copyright (c) 2023 Denis Mikhailov
//
// 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_STDARRAY_HPP
#define BOOST_PFR_DETAIL_STDARRAY_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <utility> // metaprogramming stuff
#include <array>
#include <type_traits> // for std::common_type_t
#include <cstddef>
#include <boost/pfr/detail/sequence_tuple.hpp>
namespace boost { namespace pfr { namespace detail {
template <class... Types>
constexpr auto make_stdarray(const Types&... t) noexcept {
return std::array<std::common_type_t<Types...>, sizeof...(Types)>{t...};
}
template <class T, std::size_t... I>
constexpr auto make_stdarray_from_tietuple(const T& t, std::index_sequence<I...>, int) noexcept {
return detail::make_stdarray(
boost::pfr::detail::sequence_tuple::get<I>(t)...
);
}
template <class T>
constexpr auto make_stdarray_from_tietuple(const T&, std::index_sequence<>, long) noexcept {
return std::array<std::nullptr_t, 0>{};
}
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_STDARRAY_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -17,8 +17,7 @@
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...>) {
(void)t; // workaround for MSVC 14.1 `warning C4100: 't': unreferenced formal parameter`
constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
return std::make_tuple(
boost::pfr::detail::sequence_tuple::get<I>(t)...
);
@@ -26,7 +25,6 @@ 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)...
);
@@ -34,7 +32,6 @@ constexpr auto make_stdtiedtuple_from_tietuple(const T& t, std::index_sequence<I
template <class T, std::size_t... I>
constexpr auto make_conststdtiedtuple_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
(void)t; // workaround for MSVC 14.1 `warning C4100: 't': unreferenced formal parameter`
return std::tuple<
std::add_lvalue_reference_t<std::add_const_t<
std::remove_reference_t<decltype(boost::pfr::detail::sequence_tuple::get<I>(t))>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -78,7 +78,7 @@ namespace detail {
} // namespace detail
/// \brief Compares lhs and rhs for equality using their own comparison and conversion operators; if no operators available returns \forcedlink{eq_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for equality using their own comparison and conversion operators; if no operators avalable returns \forcedlink{eq_fields}(lhs, rhs).
///
/// \returns true if lhs is equal to rhs; false otherwise
template <class T, class U>
@@ -93,7 +93,7 @@ constexpr detail::enable_eq_comp_t<T, U> eq(const T& lhs, const U& rhs) {
}
/// \brief Compares lhs and rhs for inequality using their own comparison and conversion operators; if no operators available returns \forcedlink{ne_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for inequality using their own comparison and conversion operators; if no operators avalable returns \forcedlink{ne_fields}(lhs, rhs).
///
/// \returns true if lhs is not equal to rhs; false otherwise
template <class T, class U>
@@ -108,7 +108,7 @@ constexpr detail::enable_ne_comp_t<T, U> ne(const T& lhs, const U& rhs) {
}
/// \brief Compares lhs and rhs for less-than using their own comparison and conversion operators; if no operators available returns \forcedlink{lt_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for less-than using their own comparison and conversion operators; if no operators avalable returns \forcedlink{lt_fields}(lhs, rhs).
///
/// \returns true if lhs is less than rhs; false otherwise
template <class T, class U>
@@ -123,7 +123,7 @@ constexpr detail::enable_lt_comp_t<T, U> lt(const T& lhs, const U& rhs) {
}
/// \brief Compares lhs and rhs for greater-than using their own comparison and conversion operators; if no operators available returns \forcedlink{lt_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for greater-than using their own comparison and conversion operators; if no operators avalable returns \forcedlink{lt_fields}(lhs, rhs).
///
/// \returns true if lhs is greater than rhs; false otherwise
template <class T, class U>
@@ -138,7 +138,7 @@ constexpr detail::enable_gt_comp_t<T, U> gt(const T& lhs, const U& rhs) {
}
/// \brief Compares lhs and rhs for less-equal using their own comparison and conversion operators; if no operators available returns \forcedlink{le_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for less-equal using their own comparison and conversion operators; if no operators avalable returns \forcedlink{le_fields}(lhs, rhs).
///
/// \returns true if lhs is less or equal to rhs; false otherwise
template <class T, class U>
@@ -153,7 +153,7 @@ constexpr detail::enable_le_comp_t<T, U> le(const T& lhs, const U& rhs) {
}
/// \brief Compares lhs and rhs for greater-equal using their own comparison and conversion operators; if no operators available returns \forcedlink{ge_fields}(lhs, rhs).
/// \brief Compares lhs and rhs for greater-equal using their own comparison and conversion operators; if no operators avalable returns \forcedlink{ge_fields}(lhs, rhs).
///
/// \returns true if lhs is greater or equal to rhs; false otherwise
template <class T, class U>
@@ -168,7 +168,7 @@ constexpr detail::enable_ge_comp_t<T, U> ge(const T& lhs, const U& rhs) {
}
/// \brief Hashes value using its own std::hash specialization; if no std::hash specialization available returns \forcedlink{hash_fields}(value).
/// \brief Hashes value using its own std::hash specialization; if no std::hash specialization avalable returns \forcedlink{hash_fields}(value).
///
/// \returns std::size_t with hash of the value
template <class T>

View File

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

View File

@@ -19,8 +19,8 @@
namespace boost { namespace pfr {
/// 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.
/// Has a static const member variable `value` when it 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.
///
/// \b Example:
/// \code
@@ -29,9 +29,11 @@ namespace boost { namespace pfr {
/// template<> struct is_reflectable<B, boost_fusion_tag> : std::false_type {}; // 'B' won't be interpreted as reflectable in only Boost Fusion
/// }}
/// \endcode
/// \note is_reflectable affects is_implicitly_reflectable, the decision made by is_reflectable is used by is_implicitly_reflectable.
/// \note is_reflectable affects is_implicitly_reflectable, the decision made by is_reflectable has more priority than is_implicitly_reflectable,
/// because is_reflectable is more sharp than is_implicitly_reflectable
///
template<class T, class WhatFor>
struct is_reflectable { /* does not have 'value' because value is unknown */ };
struct is_reflectable { /* do not has 'value' because value is unknown */ };
// these specs can't be inherited from 'std::integral_constant< bool, boost::pfr::is_reflectable<T, WhatFor>::value >',
// because it will break the sfinae-friendliness
@@ -44,15 +46,17 @@ struct is_reflectable<volatile T, WhatFor> : boost::pfr::is_reflectable<T, WhatF
template<class T, class WhatFor>
struct is_reflectable<const volatile T, WhatFor> : boost::pfr::is_reflectable<T, WhatFor> {};
#if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
/// Checks the input type for the potential to be reflected.
/// Specialize is_reflectable if you disagree with is_implicitly_reflectable's default decision.
/// Specialize is_reflectable if you are disagree with is_implicitly_reflectable's default decision.
template<class T, class WhatFor>
using is_implicitly_reflectable = std::integral_constant< bool, boost::pfr::detail::possible_reflectable<T, WhatFor>(1L) >;
/// Checks the input type for the potential to be reflected.
/// Specialize is_reflectable if you disagree with is_implicitly_reflectable_v's default decision.
/// Specialize is_reflectable if you are disagree with is_implicitly_reflectable_v's default decision.
template<class T, class WhatFor>
constexpr bool is_implicitly_reflectable_v = is_implicitly_reflectable<T, WhatFor>::value;
#endif
}} // namespace boost::pfr

View File

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

View File

@@ -1,18 +1,16 @@
<!DOCTYPE html>
<!--
Copyright (c) 2014-2024 Antony Polukhin
Copyright (c) 2014-2023 Antony Polukhin
antoshkka at gmail dot com
Distributed under the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt
or copy at http://boost.org/LICENSE_1_0.txt)
boost-no-inspect
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=../../doc/html/boost_pfr.html">
<meta http-equiv="refresh" content="0; url=https://www.boost.org/doc/libs/master/doc/html/boost_pfr.html">
<title>Boost.Stacktrace</title>
<style>
body {
@@ -28,10 +26,10 @@ boost-no-inspect
<body>
<p>
Automatic redirection failed, please go to
<a href="../../doc/html/boost_pfr.html">../../doc/html/boost_pfr.html</a>
<a href="https://www.boost.org/doc/libs/master/doc/html/boost_pfr.html">https://www.boost.org/doc/libs/master/doc/html/boost_pfr.html</a>
</p>
<p>
&copy; 2014-2024 Antony Polukhin
&copy; 2014-2023 Antony Polukhin
</p>
</body>
</html>

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
# Copyright (c) 2016-2024 Antony Polukhin
# Copyright (c) 2016-2023 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-2024 Antony Polukhin
PROLOGUE = """// Copyright (c) 2016-2023 Antony Polukhin
// Copyright (c) 2023 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -44,47 +44,66 @@ namespace boost { namespace pfr { namespace detail {
template <class... Args>
constexpr auto make_tuple_of_references(Args&&... args) noexcept {
return sequence_tuple::tuple<Args&...>{ args... };
return sequence_tuple::tuple<Args&&...>{ static_cast<Args&&>(args)... };
}
template<typename T, typename Arg>
constexpr decltype(auto) add_cv_like(Arg& arg) noexcept {
if constexpr (std::is_const<T>::value && std::is_volatile<T>::value) {
return const_cast<const volatile Arg&>(arg);
}
else if constexpr (std::is_const<T>::value) {
return const_cast<const Arg&>(arg);
}
else if constexpr (std::is_volatile<T>::value) {
return const_cast<volatile Arg&>(arg);
}
else {
return const_cast<Arg&>(arg);
if constexpr (std::is_rvalue_reference<T&&>::value) {
if constexpr (std::is_const<T>::value && std::is_volatile<T>::value) {
return const_cast<const volatile Arg&&>(arg);
}
else if constexpr (std::is_const<T>::value) {
return const_cast<const Arg&&>(arg);
}
else if constexpr (std::is_volatile<T>::value) {
return const_cast<volatile Arg&&>(arg);
}
else {
return const_cast<Arg&&>(arg);
}
} else {
if constexpr (std::is_const<T>::value && std::is_volatile<T>::value) {
return const_cast<const volatile Arg&>(arg);
}
else if constexpr (std::is_const<T>::value) {
return const_cast<const Arg&>(arg);
}
else if constexpr (std::is_volatile<T>::value) {
return const_cast<volatile Arg&>(arg);
}
else {
return const_cast<Arg&>(arg);
}
}
}
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78939
template<typename T, typename Sb, typename Arg>
constexpr decltype(auto) workaround_cast(Arg& arg) noexcept {
using output_arg_t = std::conditional_t<!std::is_reference<Sb>(), decltype(detail::add_cv_like<T>(arg)), Sb>;
using output_arg_t = std::conditional_t<
!std::is_reference<Sb>(),
decltype(detail::add_cv_like<T>(arg)),
std::conditional_t<std::is_rvalue_reference<T&&>::value, Sb&&, Sb&>
>;
return const_cast<output_arg_t>(arg);
}
template <class T>
constexpr auto tie_as_tuple(T& /*val*/, size_t_<0>) noexcept {
constexpr auto tie_as_tuple(const T& /*val*/, size_t_<0>) noexcept {
return sequence_tuple::tuple<>{};
}
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
auto& [a] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.
constexpr auto tie_as_tuple(T&& val, size_t_<1>, std::enable_if_t<std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
auto&& [a] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.
return ::boost::pfr::detail::make_tuple_of_references(detail::workaround_cast<T, decltype(a)>(a));
}
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<!std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
return ::boost::pfr::detail::make_tuple_of_references( val );
constexpr auto tie_as_tuple(T&& val, size_t_<1>, std::enable_if_t<!std::is_class< std::remove_cv_t<T> >::value>* = nullptr) noexcept {
return ::boost::pfr::detail::make_tuple_of_references( std::forward<T>(val) );
}
"""
@@ -92,7 +111,7 @@ constexpr auto tie_as_tuple(T& val, size_t_<1>, std::enable_if_t<!std::is_class<
############################################################################################################################
EPILOGUE = """
template <class T, std::size_t I>
constexpr void tie_as_tuple(T& /*val*/, size_t_<I>) noexcept {
constexpr void tie_as_tuple(T&& /*val*/, size_t_<I>) noexcept {
static_assert(sizeof(T) && false,
"====================> Boost.PFR: Too many fields in a structure T. Regenerate include/boost/pfr/detail/core17_generated.hpp file for appropriate count of fields. For example: `python ./misc/generate_cpp17.py 300 > include/boost/pfr/detail/core17_generated.hpp`");
}
@@ -151,11 +170,11 @@ for i in range(1, funcs_count):
empty_printer = EmptyLinePrinter()
print("template <class T>")
print("constexpr auto tie_as_tuple(T& val, size_t_<" + str(i + 1) + ">) noexcept {")
print("constexpr auto tie_as_tuple(T&& val, size_t_<" + str(i + 1) + ">) noexcept {")
if i < max_args_on_a_line:
print(" auto& [" + indexes.strip() + "] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
print(" auto&& [" + indexes.strip() + "] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
else:
print(" auto& [")
print(" auto&& [")
print(indexes)
print(" ] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
empty_printer.print_once()

View File

@@ -1,267 +0,0 @@
# Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
#
# 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)
# Initial implementation by Bela Schaum, https://github.com/schaumb
# The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
#
############################################################################################################################
import sys
import string
import random
# a bigger value might lead to compiler out of heap space error on MSVC
STRUCT_COUNT = 50
MAX_FIELD_COUNT = 50
MAIN_TEMPLATE = """// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov, 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)
// Generated by misc/generate_fields_names_big.cpp.py
#include <boost/pfr/core_name.hpp>
#include <type_traits>
#include <boost/core/lightweight_test.hpp>
namespace testing {
template <class... Types>
auto make_stdarray(const Types&... t) {
return std::array<std::common_type_t<Types...>, sizeof...(Types)>{t...};
}
%STRUCTS_LIST%
%TEST_GET_NAME_DEFINITIONS_LIST%
%TEST_GET_NAMES_AS_ARRAY_DEFINITIONS_LIST%
} // namespace testing
int main() {
%TEST_GET_NAME_CALLS_LIST%
%TEST_GET_NAMES_AS_ARRAY_CALLS_LIST%
return boost::report_errors();
}
"""
STRUCT_TEMPLATE = """struct Aggregate%STRUCT_ID% {
%FIELD_DEFINITIONS_LIST%
};
"""
STRUCT_FIELD_DEFINITION_TEMPLATE = """int %FIELD_NAME%;
"""
TEST_GET_NAME_TEMPLATE = """void test_get_name_%TEST_ID%() {
%CHECKERS_LIST%
}
"""
TEST_GET_NAME_CHECKER_TEMPLATE = """BOOST_TEST_EQ( ((boost::pfr::get_name<%FIELD_ID%, Aggregate%STRUCT_ID%>())), "%FIELD_NAME%");
"""
TEST_GET_NAMES_AS_ARRAY_TEMPLATE = """void test_names_as_array_%TEST_ID%() {
const auto expected = make_stdarray(
%FIELD_NAMES_LIST%
);
const auto value = boost::pfr::names_as_array<Aggregate%STRUCT_ID%>();
BOOST_TEST_EQ(expected.size(), value.size());
for (std::size_t i=0;i<expected.size();++i) {
BOOST_TEST_EQ(value[i], expected[i]);
}
}
"""
FIELD_NAME_TEMPLATE = """std::string_view{"%FIELD_NAME%"}
"""
TEST_GET_NAME_CALL_TEMPLATE = """testing::test_get_name_%TEST_ID%();
"""
TEST_GET_NAMES_AS_ARRAY_CALL_TEMPLATE = """testing::test_names_as_array_%TEST_ID%();
"""
############################################################################################################################
field_names = {
"alignas": True,
"alignof": True,
"and": True,
"and_eq": True,
"asm": True,
"atomic_cancel": True,
"atomic_commit": True,
"atomic_noexcept": True,
"auto": True,
"bitand": True,
"bitor": True,
"bool": True,
"break": True,
"case": True,
"catch": True,
"char": True,
"char8_t": True,
"char16_t": True,
"char32_t": True,
"class": True,
"compl": True,
"concept": True,
"const": True,
"consteval": True,
"constexpr": True,
"constinit": True,
"const_cast": True,
"continue": True,
"co_await": True,
"co_return": True,
"co_yield": True,
"decltype": True,
"default": True,
"delete": True,
"do": True,
"double": True,
"dynamic_cast": True,
"else": True,
"enum": True,
"explicit": True,
"export": True,
"extern": True,
"false": True,
"float": True,
"for": True,
"friend": True,
"goto": True,
"if": True,
"inline": True,
"int": True,
"long": True,
"mutable": True,
"namespace": True,
"new": True,
"noexcept": True,
"not": True,
"not_eq": True,
"nullptr": True,
"operator": True,
"or": True,
"or_eq": True,
"private": True,
"protected": True,
"public": True,
"reflexpr": True,
"register": True,
"reinterpret_cast": True,
"requires": True,
"return": True,
"short": True,
"signed": True,
"sizeof": True,
"static": True,
"static_assert": True,
"static_cast": True,
"struct": True,
"switch": True,
"synchronized": True,
"template": True,
"this": True,
"thread_local": True,
"throw": True,
"true": True,
"try": True,
"typedef": True,
"typeid": True,
"typename": True,
"union": True,
"unsigned": True,
"using": True,
"virtual": True,
"void": True,
"volatile": True,
"wchar_t": True,
"while": True,
"xor": True,
"xor_eq": True
}
field_names_by_id = {}
def generate_new_field_name():
result = ''
name_len = random.randint(1,100)
result += random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")
for i in range(name_len-1):
result += random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789")
return result
def generate_field_name(struct_id, field_id):
key = (struct_id, field_id)
if not key in field_names_by_id:
new_name = generate_new_field_name()
while new_name in field_names:
new_name = generate_new_field_name()
field_names[new_name] = True
field_names_by_id[key] = new_name
return field_names_by_id[key]
def generate_struct(struct_id):
field_definitions = ''
fields_count = struct_id
for i in range(fields_count):
field_definitions += STRUCT_FIELD_DEFINITION_TEMPLATE.replace('%FIELD_NAME%', generate_field_name(struct_id, i))
return STRUCT_TEMPLATE.replace('%FIELD_DEFINITIONS_LIST%', field_definitions).replace('%STRUCT_ID%', str(struct_id))
def generate_structs_list():
result = ''
for i in range(STRUCT_COUNT):
result += generate_struct(i+1)
return result
def generate_test_get_name_definition(struct_id):
checkers_list = ''
fields_count = struct_id
for i in range(fields_count):
checkers_list += TEST_GET_NAME_CHECKER_TEMPLATE.replace('%FIELD_ID%', str(i)).replace('%STRUCT_ID%', str(struct_id)).replace('%FIELD_NAME%', generate_field_name(struct_id, i))
return TEST_GET_NAME_TEMPLATE.replace('%TEST_ID%', str(struct_id)).replace('%CHECKERS_LIST%', checkers_list)
def generate_test_get_name_definitions_list():
result = ''
for i in range(STRUCT_COUNT):
result += generate_test_get_name_definition(i+1)
return result
def generate_test_names_as_array_definition(struct_id):
field_names_list = FIELD_NAME_TEMPLATE.replace('%FIELD_NAME%', generate_field_name(struct_id, 0))
fields_count = struct_id
for i in range(1, fields_count):
field_names_list += ', ' + FIELD_NAME_TEMPLATE.replace('%FIELD_NAME%', generate_field_name(struct_id, i))
return TEST_GET_NAMES_AS_ARRAY_TEMPLATE.replace('%TEST_ID%', str(struct_id)).replace('%FIELD_NAMES_LIST%', field_names_list).replace('%STRUCT_ID%', str(struct_id))
def generate_test_names_as_array_definitions_list():
result = ''
for i in range(STRUCT_COUNT):
result += generate_test_names_as_array_definition(i+1)
return result
def generate_test_get_name_calls_list():
result = ''
for i in range(STRUCT_COUNT):
result += TEST_GET_NAME_CALL_TEMPLATE.replace('%TEST_ID%', str(i+1))
return result
def generate_test_names_as_array_calls_list():
result = ''
for i in range(STRUCT_COUNT):
result += TEST_GET_NAMES_AS_ARRAY_CALL_TEMPLATE.replace('%TEST_ID%', str(i+1))
return result
print(MAIN_TEMPLATE.replace('%STRUCTS_LIST%', generate_structs_list()).replace('%TEST_GET_NAME_DEFINITIONS_LIST%', generate_test_get_name_definitions_list()).replace('%TEST_GET_NAMES_AS_ARRAY_DEFINITIONS_LIST%', generate_test_names_as_array_definitions_list()).replace('%TEST_GET_NAME_CALLS_LIST%', generate_test_get_name_calls_list()).replace('%TEST_GET_NAMES_AS_ARRAY_CALLS_LIST%', generate_test_names_as_array_calls_list()))

View File

@@ -39,46 +39,26 @@ find ${TARGET_PATH}/doc -type f | xargs sed -i 's|Boost.PFR|PFR|g'
sed -i 's|# \[Boost.PFR\](https://boost.org/libs/pfr)|# [PFR](https://apolukhin.github.io/pfr_non_boost/)|g' ${TARGET_PATH}/README.md
echo -n "***** Testing: "
if g++-12 -std=c++2a -DPFR_ENABLE_GET_NAME_STATIC=1 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
if g++-9 -std=c++17 -DPFR_USE_LOOPHOLE=0 -DPFR_USE_CPP17=1 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
echo -n "OK"
else
echo -n "FAIL"
exit 2
fi
if g++-12 -std=c++2a -DPFR_ENABLE_GET_NAME_STATIC=0 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
echo -n "OK"
if g++-9 -std=c++17 -DPFR_USE_LOOPHOLE=1 -DPFR_USE_CPP17=0 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
echo -n ", OK"
else
echo -n "FAIL"
echo -n ", FAIL"
exit 3
fi
if g++-12 -std=c++2a -DPFR_ENABLE_GET_NAME_STATIC=1 -DBOOST_PFR_USE_CPP17=1 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/get_name.cpp && ./a.out > /dev/null; then
if g++-9 -std=c++17 -DPFR_USE_LOOPHOLE=0 -DPFR_USE_CPP17=0 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/get.cpp && ./a.out > /dev/null; then
echo -e ", OK"
else
echo -e ", FAIL"
exit 4
fi
if g++-12 -std=c++2a -DPFR_USE_LOOPHOLE=0 -DPFR_USE_CPP17=1 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
echo -n "OK"
else
echo -n "FAIL"
exit 5
fi
if g++-12 -std=c++2a -DPFR_USE_LOOPHOLE=1 -DPFR_USE_CPP17=0 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/motivating_example0.cpp && ./a.out > /dev/null; then
echo -n ", OK"
else
echo -n ", FAIL"
exit 6
fi
if g++-12 -std=c++2a -DPFR_USE_LOOPHOLE=0 -DPFR_USE_CPP17=0 -I ${TARGET_PATH}/include/ ${TARGET_PATH}/example/get.cpp && ./a.out > /dev/null; then
echo -e ", OK"
else
echo -e ", FAIL"
exit 7
fi
rm a.out || :
echo "***** Done"

View File

@@ -6,5 +6,4 @@
#
build-project config ;
build-project core ;
build-project core_name ;
build-project core ;

View File

@@ -1,13 +1,9 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
#include <boost/pfr/config.hpp>
#if BOOST_PFR_ENABLED
#include <boost/pfr.hpp>
#endif
#include <boost/preprocessor/stringize.hpp>
#include <boost/pfr/config.hpp> // inclusion of an another PFR header may fail when BOOST_PFR_ENABLED=0
#include <iostream>
@@ -18,9 +14,6 @@ int main() {
<< "BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == " << BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE << '\n'
<< "BOOST_PFR_HAS_GUARANTEED_COPY_ELISION == " << BOOST_PFR_HAS_GUARANTEED_COPY_ELISION << '\n'
<< "BOOST_PFR_ENABLE_IMPLICIT_REFLECTION == " << BOOST_PFR_ENABLE_IMPLICIT_REFLECTION << '\n'
<< "BOOST_PFR_CORE_NAME_ENABLED == " << BOOST_PFR_CORE_NAME_ENABLED << '\n'
<< "BOOST_PFR_FUNCTION_SIGNATURE == " << BOOST_PP_STRINGIZE(BOOST_PFR_FUNCTION_SIGNATURE) << '\n'
<< "BOOST_PFR_CORE_NAME_PARSING == " << BOOST_PP_STRINGIZE(BOOST_PFR_CORE_NAME_PARSING) << '\n'
<< "BOOST_PFR_ENABLED == " << BOOST_PFR_ENABLED << '\n'
<< "__cplusplus == " << __cplusplus << '\n'
#ifdef __cpp_structured_bindings

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2016-2024 Antony Polukhin
// 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)
@@ -56,21 +56,6 @@ struct simple {
struct empty{};
#if BOOST_PFR_USE_CPP17
constexpr std::size_t get_field_count_through_for_each_field() {
std::size_t counter = 0;
boost::pfr::for_each_field(simple{}, [&counter](auto&& /*val*/, std::size_t /*i*/) {
++ counter;
});
return counter;
}
// MSVC-14.1 fails to compile the following code
#if !defined(_MSC_VER) || _MSC_VER > 1916
static_assert(3 == get_field_count_through_for_each_field());
#endif
#endif
int main () {
std::size_t control = 0;

View File

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

View File

@@ -1,67 +0,0 @@
// 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)
#include <boost/pfr/core.hpp>
#include <boost/core/lightweight_test.hpp>
namespace testing {
namespace {
struct Aggregate {
int a;
const int b;
double c;
double d;
short e;
};
void test_get_by_type() {
#if BOOST_PFR_USE_CPP17
Aggregate t{1, 2, 3.4, 5.6, 7};
BOOST_TEST_EQ(boost::pfr::get<int>(t), 1);
BOOST_TEST_EQ(boost::pfr::get<const int>(t), 2);
BOOST_TEST_EQ(boost::pfr::get<short>(t), 7);
boost::pfr::get<int>(t) = 11;
boost::pfr::get<short>(t) = 77;
#endif
}
void test_const_get_by_type() {
#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
const Aggregate t{1, 2, 3.4, 5.6, 7};
BOOST_TEST_EQ(boost::pfr::get<short>(t), 7);
#endif
}
void test_get_by_type_pod() {
struct PodAggregate {
int i;
short s;
};
PodAggregate pod{1, 2};
BOOST_TEST_EQ(boost::pfr::get<int>(pod), 1);
BOOST_TEST_EQ(boost::pfr::get<short>(pod), 2);
}
} // anonymous namespace
} // namespace testing
int main() {
testing::test_get_by_type();
testing::test_const_get_by_type();
testing::test_get_by_type_pod();
return boost::report_errors();
}

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2024 Antony Polukhin
// Copyright (c) 2018-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)
@@ -6,7 +6,6 @@
// Test case for https://github.com/boostorg/pfr/issues/33
#include <iostream>
#include <memory>
#include <vector>
#include <boost/pfr.hpp>
#include <boost/core/lightweight_test.hpp>
@@ -15,23 +14,13 @@ struct TestStruct {
std::vector<std::unique_ptr<int>> vec;
};
int main() {
TestStruct temp;
temp.vec.emplace_back();
// FIXME: https://github.com/boostorg/pfr/issues/131
#if defined(__clang__) && __cplusplus >= 202002L
# if BOOST_PFR_USE_LOOPHOLE == 0 && BOOST_PFR_USE_CPP17 == 0
# error This test should fail on classic engine
#endif
#else
boost::pfr::for_each_field(temp, [](const auto& value) {
BOOST_TEST_EQ(value.size(), 1);
});
#endif
return boost::report_errors();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2018-2024 Antony Polukhin
// Copyright (c) 2018-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)
@@ -18,11 +18,7 @@ struct X {
struct S { X x0; X x1; int x2; X x3; };
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
static_assert(boost::pfr::tuple_size_v<S> == 4, "");
struct S5_0 { int x0; int x1; int x2; int x3; X x4; };
@@ -42,8 +38,6 @@ int main() {
struct S6 { X x0; X x1; X x2; X x3; X x4; X x5;};
static_assert(boost::pfr::tuple_size_v<S6> == 6, "");
#endif
#endif // #if BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
return boost::report_errors();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,91 +0,0 @@
// 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)
#include <boost/core/lightweight_test.hpp>
#include <boost/pfr/core.hpp>
namespace some {
struct struct1{ int i; };
struct struct2{ int i; short s; };
}
void test_single_field() {
{
some::struct1 s{1};
auto s_tuple = boost::pfr::structure_to_tuple(s);
BOOST_TEST_EQ(std::get<0>(s_tuple), 1);
static_assert(std::is_same<
std::tuple<int>, decltype(s_tuple)
>::value, "");
}
{
const some::struct1 s{1};
auto s_tuple = boost::pfr::structure_to_tuple(s);
BOOST_TEST_EQ(std::get<0>(s_tuple), 1);
static_assert(std::is_same<
std::tuple<int>, decltype(s_tuple)
>::value, "");
}
}
void test_two_fields() {
{
some::struct2 s{1, 2};
auto s_tuple = boost::pfr::structure_to_tuple(s);
BOOST_TEST_EQ(std::get<0>(s_tuple), 1);
BOOST_TEST_EQ(std::get<1>(s_tuple), 2);
static_assert(std::is_same<
std::tuple<int, short>, decltype(s_tuple)
>::value, "");
}
{
const some::struct2 s{1, 2};
auto s_tuple = boost::pfr::structure_to_tuple(s);
BOOST_TEST_EQ(std::get<0>(s_tuple), 1);
BOOST_TEST_EQ(std::get<1>(s_tuple), 2);
static_assert(std::is_same<
std::tuple<int, short>, decltype(s_tuple)
>::value, "");
}
}
// Test from https://github.com/boostorg/pfr/issues/155
void test_throwing_field() {
#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
struct throw_on_copy {
throw_on_copy() = default;
throw_on_copy(const throw_on_copy&){ throw 42; }
};
struct throwing_struct {
int i;
throw_on_copy s;
};
throwing_struct s {10, {}};
try {
std::tuple<int, throw_on_copy> t = boost::pfr::structure_to_tuple(s);
BOOST_TEST(false); // the above line should throw
(void)t;
} catch (...) {}
#endif
}
int main() {
test_single_field();
test_two_fields();
test_throwing_field();
return boost::report_errors();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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