mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-20 04:42:22 +00:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0bf18798c | ||
|
|
9bc057e2a6 | ||
|
|
e460ce2ddc | ||
|
|
d66c0a9551 | ||
|
|
95c06fb7c6 | ||
|
|
ab509a5b32 | ||
|
|
ed28602c2c | ||
|
|
dbc78d7dd9 | ||
|
|
551174b58c | ||
|
|
79b0d65d4f | ||
|
|
2116be9285 | ||
|
|
a9a295e4aa | ||
|
|
2775d19f34 | ||
|
|
633c4bc985 | ||
|
|
b1af355a49 | ||
|
|
ef505f10c3 | ||
|
|
1be5e116f4 | ||
|
|
bca51da20f | ||
|
|
47c6413530 | ||
|
|
52a5a489ba | ||
|
|
fd584a405d | ||
|
|
b6a960757b | ||
|
|
dac40b2153 | ||
|
|
58ce59cf38 | ||
|
|
5010309967 | ||
|
|
bf5bd10b36 | ||
|
|
3279a7b610 | ||
|
|
d7db07e98d | ||
|
|
6a38a07285 | ||
|
|
69a06b98da | ||
|
|
578b5b2ac2 | ||
|
|
f12f35ac1a | ||
|
|
2b4e2922ae | ||
|
|
b2acaacaaf | ||
|
|
ff6c2b87c0 | ||
|
|
2a3ddbfc17 | ||
|
|
5374f9aebc | ||
|
|
968d692c5e | ||
|
|
5c13668343 | ||
|
|
6f853dad2c | ||
|
|
aa5abd8d76 | ||
|
|
ba40d86097 | ||
|
|
7a3a419c35 | ||
|
|
a70d02103a | ||
|
|
d59b6f9520 | ||
|
|
69c5692cd6 | ||
|
|
8f325567eb | ||
|
|
b10c0c66ed | ||
|
|
1bb4ced005 | ||
|
|
58dcb40a49 | ||
|
|
b7d839b851 | ||
|
|
3396cdca9e | ||
|
|
fbafd21118 | ||
|
|
b0aae28eb0 | ||
|
|
9388c4e4c0 | ||
|
|
4e84a5b159 | ||
|
|
7837449ca7 | ||
|
|
9bb809d2a5 | ||
|
|
2a1fd53724 | ||
|
|
cae0eaad61 | ||
|
|
ba10f9bc94 | ||
|
|
8a8b5bc8d3 | ||
|
|
a73f25d3ff | ||
|
|
a24717a4a1 | ||
|
|
10848f71ae | ||
|
|
7d925660bb | ||
|
|
87e77b9b43 | ||
|
|
b331ef58f5 | ||
|
|
5579d11588 | ||
|
|
51f6422c07 | ||
|
|
87c9c2d76c | ||
|
|
d1e7e87a31 | ||
|
|
14185d614f | ||
|
|
0436e48a79 | ||
|
|
4d9294cb1f | ||
|
|
e75c066ddc | ||
|
|
e51a594dbb | ||
|
|
12f2b3a365 | ||
|
|
2a1b206244 | ||
|
|
b4bee46c54 | ||
|
|
444094f20d | ||
|
|
da12b52759 |
44
.github/workflows/ci.yml
vendored
44
.github/workflows/ci.yml
vendored
@@ -17,14 +17,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-16.04
|
||||
install: g++-4.8
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
- toolset: gcc-9
|
||||
- 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-18.04
|
||||
- toolset: gcc-10
|
||||
@@ -33,29 +29,18 @@ jobs:
|
||||
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
|
||||
linkflags: "linkflags=--coverage -lasan -lubsan"
|
||||
gcov_tool: "gcov-10"
|
||||
- toolset: clang
|
||||
compiler: clang++-3.7
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.7
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17" # Do not run in 2a mode because of the "chrono:1345:24: error: unknown type name 'strong_ordering'"
|
||||
os: ubuntu-20.04
|
||||
cxxflags: "cxxflags=--coverage"
|
||||
linkflags: "linkflags=--coverage"
|
||||
gcov_tool: "llvm-cov-9 gcov"
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
cxxflags: "cxxflags=-fsanitize=address,undefined,integer -fno-sanitize-recover=undefined"
|
||||
linkflags: "linkflags=-fsanitize=address,undefined,integer"
|
||||
- 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"
|
||||
# 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}}
|
||||
|
||||
@@ -102,6 +87,10 @@ jobs:
|
||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
|
||||
dist/bin/inspect libs/$LIBRARY
|
||||
|
||||
- name: Test boost namespace stripping
|
||||
if: ${{matrix.toolset == 'gcc-9'}}
|
||||
run: ../boost-root/libs/$LIBRARY/misc/strip_boost_namespace.sh
|
||||
|
||||
- name: Prepare coverage data
|
||||
if: matrix.gcov_tool
|
||||
run: |
|
||||
@@ -135,10 +124,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.1
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2016
|
||||
# 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"
|
||||
@@ -168,7 +158,7 @@ jobs:
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
|
||||
178
.travis.yml
178
.travis.yml
@@ -1,178 +0,0 @@
|
||||
# Use, modification, and distribution are
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Copyright Antony Polukhin 2014-2020.
|
||||
|
||||
#
|
||||
# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file
|
||||
# and how it can be used with Boost libraries.
|
||||
#
|
||||
# File revision #9 (with DIFF)
|
||||
|
||||
language: cpp
|
||||
os: linux
|
||||
dist: bionic
|
||||
|
||||
# `--coverage` flags required to generate coverage info for Coveralls
|
||||
matrix:
|
||||
include:
|
||||
# - env: B2_ARGS='cxxstd=14,1y toolset=gcc-6 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD -fno-rtti" linkflags="--coverage -lasan -lubsan"'
|
||||
# name: "GCC-6, no RTTI"
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ubuntu-toolchain-r-test
|
||||
# packages: g++-6
|
||||
|
||||
- env: B2_ARGS='cxxstd=14,17,2a toolset=gcc-10 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD" linkflags="--coverage -lasan -lubsan"'
|
||||
name: "GCC-10"
|
||||
sudo: required # Required by leak sanitizer
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages: g++-10
|
||||
|
||||
- env: B2_ARGS='cxxstd=14,17,2a toolset=gcc-8 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD" linkflags="--coverage -lasan -lubsan"'
|
||||
name: "GCC-8"
|
||||
sudo: required # Required by leak sanitizer
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages: g++-8
|
||||
|
||||
- env: B2_ARGS='cxxstd=1y toolset=gcc-5 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD" linkflags="--coverage -lasan -lubsan"'
|
||||
name: "GCC-5"
|
||||
addons:
|
||||
apt:
|
||||
sources: ubuntu-toolchain-r-test
|
||||
packages: g++-5
|
||||
|
||||
# - env: B2_ARGS='cxxstd=14,1y toolset=gcc-8 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD -fno-exceptions" linkflags="--coverage -lasan -lubsan"'
|
||||
# name: "GCC-8, no exceptions"
|
||||
# sudo: required # Required by leak sanitizer
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ubuntu-toolchain-r-test
|
||||
# packages: g++-8
|
||||
|
||||
- env: B2_ARGS='cxxstd=14 toolset=clang-6 cxxflags="--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD" linkflags="--coverage -fsanitize=address,leak,undefined"'
|
||||
name: "Clang-6"
|
||||
sudo: required # Required by leak sanitizer
|
||||
addons:
|
||||
apt:
|
||||
sources: llvm-toolchain-trusty-6
|
||||
packages: clang-6.0
|
||||
|
||||
- env: B2_ARGS='cxxstd=14,17,20 toolset=clang-10 cxxflags="-stdlib=libc++ --coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined -DBOOST_TRAVISCI_BUILD" linkflags="-stdlib=libc++ --coverage -fsanitize=address,leak,undefined"'
|
||||
name: "Clang-10, libc++"
|
||||
sudo: required # Required by leak sanitizer
|
||||
addons:
|
||||
apt:
|
||||
sources: llvm-toolchain-bionic-10
|
||||
packages:
|
||||
- clang-10
|
||||
- libc++-10-dev
|
||||
- libc++abi-10-dev
|
||||
|
||||
# Sanitizers disabled for this toolset as they started causing link troubles:
|
||||
# hidden symbol `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE11__recommendEm' isn't defined
|
||||
- env: B2_ARGS='cxxstd=14 toolset=clang-libc++ cxxflags="--coverage -DBOOST_TRAVISCI_BUILD" linkflags="--coverage"'
|
||||
name: "Clang-3.8, libc++"
|
||||
addons:
|
||||
apt:
|
||||
packages: libc++-dev
|
||||
|
||||
###############################################################################################################
|
||||
# From this point and below code is same for all the Boost libs
|
||||
###############################################################################################################
|
||||
|
||||
# Installing additional tools
|
||||
addons:
|
||||
apt:
|
||||
sources: git-core
|
||||
packages:
|
||||
- git
|
||||
- python-yaml
|
||||
|
||||
before_install:
|
||||
# Autodetect Boost branch by using the following code: - BOOST_BRANCH=$TRAVIS_BRANCH
|
||||
# or just directly specify it
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
|
||||
# Files, which coverage results must be ignored (files from other projects).
|
||||
# Example: - IGNORE_COVERAGE='*/boost/progress.hpp */filesystem/src/*'
|
||||
- IGNORE_COVERAGE=''
|
||||
|
||||
# Explicitly remove the following library from Boost and use the folder for tests. This may be usefull, if you're for example running Travis
|
||||
# from `Boost.DLL` repo, while Boost already has `dll`.
|
||||
#
|
||||
# By default is eaual to - BOOST_LIBS_FOLDER=$(basename $TRAVIS_BUILD_DIR)
|
||||
# This will force to use local repo content, instead of the Boost's default.
|
||||
- BOOST_LIBS_FOLDER=pfr #$(basename $TRAVIS_BUILD_DIR)
|
||||
|
||||
# Global options for sanitizers
|
||||
- UBSAN_OPTIONS=print_stacktrace=1
|
||||
- LSAN_OPTIONS=verbosity=1:log_threads=1
|
||||
|
||||
# Cloning minimal set of Boost libraries
|
||||
- BOOST=$HOME/boost-local
|
||||
- echo "Testing $BOOST_LIBS_FOLDER, to remove $BOOST/libs/$BOOST_LIBS_FOLDER, testing branch $BOOST_BRANCH"
|
||||
- git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git $BOOST
|
||||
- cd $BOOST
|
||||
- git submodule update --init --depth 10 tools/build tools/boostdep tools/inspect libs/filesystem
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" $BOOST/libs/filesystem
|
||||
|
||||
# Replacing Boost module with this project and installing Boost dependencies
|
||||
- rm -rf $BOOST/libs/$BOOST_LIBS_FOLDER
|
||||
- mv $TRAVIS_BUILD_DIR $BOOST/libs/$BOOST_LIBS_FOLDER
|
||||
- TRAVIS_BUILD_DIR=$BOOST/libs/$BOOST_LIBS_FOLDER
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" -I example -I examples $(basename $TRAVIS_BUILD_DIR)
|
||||
- git status
|
||||
|
||||
# Adding missing toolsets and preparing Boost headers
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
- ./b2 -j4 variant=debug tools/inspect/build
|
||||
- |-
|
||||
echo "using gcc ;" >> ~/user-config.jam
|
||||
echo "using clang ;" >> ~/user-config.jam
|
||||
echo "using clang : 3.8 : clang++-3.8 ;" >> ~/user-config.jam
|
||||
echo "using clang : 4 : clang++-4.0 ;" >> ~/user-config.jam
|
||||
echo "using clang : 5 : clang++-5.0 ;" >> ~/user-config.jam
|
||||
echo "using clang : 6 : clang++-6.0 ;" >> ~/user-config.jam
|
||||
echo "using clang : 7 : clang++-7.0 ;" >> ~/user-config.jam
|
||||
echo "using clang : 8 : clang++-8 ;" >> ~/user-config.jam
|
||||
echo "using clang : 10 : clang++-10 ;" >> ~/user-config.jam
|
||||
echo "using clang : libc++ : clang++-libc++ ;" >> ~/user-config.jam
|
||||
- cd $BOOST/libs/$BOOST_LIBS_FOLDER/test/
|
||||
|
||||
script:
|
||||
- sh -c "../../../b2 -j2 $B2_ARGS"
|
||||
- ../../../dist/bin/inspect ..
|
||||
|
||||
after_success:
|
||||
- exit 0 # we run coverage reports from GithubActions
|
||||
|
||||
# Copying Coveralls data to a separate folder
|
||||
- mkdir -p $TRAVIS_BUILD_DIR/coverals
|
||||
- wget https://github.com/linux-test-project/lcov/archive/v1.15.zip
|
||||
- unzip v1.15.zip
|
||||
- LCOV="`pwd`/lcov-1.15/bin/lcov"
|
||||
|
||||
# Preparing Coveralls data by changind data format to a readable one
|
||||
- echo "$LCOV --directory $BOOST/bin.v2/libs/$BOOST_LIBS_FOLDER --base-directory `pwd` --capture --output-file $TRAVIS_BUILD_DIR/coverals/coverage.info"
|
||||
- $LCOV --directory $BOOST/bin.v2/libs/$BOOST_LIBS_FOLDER --base-directory `pwd` --capture --output-file $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
|
||||
# ... erasing /test/ /example/ folder data
|
||||
- cd $BOOST
|
||||
- $LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info "/usr*" "*/$BOOST_LIBS_FOLDER/test/*" $IGNORE_COVERAGE "*/$BOOST_LIBS_FOLDER/tests/*" "*/$BOOST_LIBS_FOLDER/examples/*" "*/$BOOST_LIBS_FOLDER/example/*" -o $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
|
||||
# ... erasing data that is not related to this project directly
|
||||
- OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/$BOOST_LIBS_FOLDER\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'`
|
||||
- echo $OTHER_LIBS
|
||||
- eval "$LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info $OTHER_LIBS -o $TRAVIS_BUILD_DIR/coverals/coverage.info"
|
||||
|
||||
# Sending data to Coveralls
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- gem install coveralls-lcov
|
||||
- coveralls-lcov coverals/coverage.info
|
||||
20
CMakeLists.txt
Normal file
20
CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
# Generated by `boostdep --cmake pfr`
|
||||
# Copyright 2020 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(boost_pfr VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_pfr INTERFACE)
|
||||
add_library(Boost::pfr ALIAS boost_pfr)
|
||||
|
||||
target_include_directories(boost_pfr INTERFACE include)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
|
||||
66
README.md
66
README.md
@@ -2,14 +2,16 @@
|
||||
|
||||
This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other `std::tuple` like methods for user defined types without any macro or boilerplate code.
|
||||
|
||||
Boost.PFR is a part of the [Boost C++ Libraries](https://github.com/boostorg). However, Boost.PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder from the github into your project, and the library will work fine.
|
||||
[Boost.PFR](https://boost.org/libs/pfr) is a part of the [Boost C++ Libraries](https://github.com/boostorg). However, Boost.PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder from the github into your project, and the library will work fine.
|
||||
|
||||
For a version of the library without `boost::` namespace see [PFR](https://github.com/apolukhin/pfr_non_boost).
|
||||
|
||||
### Test results
|
||||
|
||||
Branches | Build | Tests coverage | More info
|
||||
----------------|-------------- | -------------- |-----------
|
||||
Develop: | [](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [](https://travis-ci.org/apolukhin/magic_get) [](https://ci.appveyor.com/project/apolukhin/magic-get/branch/develop) | [](https://coveralls.io/github/apolukhin/magic_get?branch=develop) | [details...](https://www.boost.org/development/tests/develop/developer/pfr.html)
|
||||
Master: | [](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [](https://travis-ci.org/apolukhin/magic_get) [](https://ci.appveyor.com/project/apolukhin/magic-get/branch/master) | [](https://coveralls.io/github/apolukhin/magic_get?branch=master) | [details...](https://www.boost.org/development/tests/master/developer/pfr.html)
|
||||
Develop: | [](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/pfr/branch/develop) | [](https://coveralls.io/github/apolukhin/magic_get?branch=develop) | [details...](https://www.boost.org/development/tests/develop/developer/pfr.html)
|
||||
Master: | [](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/apolukhin/pfr/branch/master) | [](https://coveralls.io/github/apolukhin/magic_get?branch=master) | [details...](https://www.boost.org/development/tests/master/developer/pfr.html)
|
||||
|
||||
[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_pfr.html)
|
||||
|
||||
@@ -43,11 +45,13 @@ Outputs:
|
||||
Edgar Allan Poe was born in 1809
|
||||
```
|
||||
|
||||
[Run the above sample](https://godbolt.org/z/PfYsWKb7v)
|
||||
|
||||
|
||||
### Motivating Example #1
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include "boost/pfr/precise.hpp"
|
||||
#include "boost/pfr.hpp"
|
||||
|
||||
struct my_struct { // no ostream operator defined!
|
||||
int i;
|
||||
@@ -72,7 +76,7 @@ my_struct has 3 fields: {100, H, 3.14159}
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include "boost/pfr/precise.hpp"
|
||||
#include "boost/pfr.hpp"
|
||||
|
||||
struct my_struct { // no ostream operator defined!
|
||||
std::string s;
|
||||
@@ -92,6 +96,58 @@ Outputs:
|
||||
my_struct has 2 fields: {"Das ist fantastisch!", 100}
|
||||
```
|
||||
|
||||
### Motivating Example #3
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config/warning_disable.hpp>
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/include/adapt_boost_pfr.hpp>
|
||||
|
||||
#include "boost/pfr/io.hpp"
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
struct ast_employee { // No BOOST_FUSION_ADAPT_STRUCT defined
|
||||
int age;
|
||||
std::string forename;
|
||||
std::string surname;
|
||||
double salary;
|
||||
};
|
||||
|
||||
auto const quoted_string = x3::lexeme['"' >> +(x3::ascii::char_ - '"') >> '"'];
|
||||
|
||||
x3::rule<class employee, ast_employee> const employee = "employee";
|
||||
auto const employee_def =
|
||||
x3::lit("employee")
|
||||
>> '{'
|
||||
>> x3::int_ >> ','
|
||||
>> quoted_string >> ','
|
||||
>> quoted_string >> ','
|
||||
>> x3::double_
|
||||
>> '}'
|
||||
;
|
||||
BOOST_SPIRIT_DEFINE(employee);
|
||||
|
||||
int main() {
|
||||
std::string str = R"(employee{34, "Chip", "Douglas", 2500.00})";
|
||||
ast_employee emp;
|
||||
x3::phrase_parse(str.begin(),
|
||||
str.end(),
|
||||
employee,
|
||||
x3::ascii::space,
|
||||
emp);
|
||||
std::cout << boost::pfr::io(emp) << std::endl;
|
||||
}
|
||||
|
||||
```
|
||||
Outputs:
|
||||
```
|
||||
(34 Chip Douglas 2500)
|
||||
```
|
||||
|
||||
|
||||
### Requirements and Limitations
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ local doxygen_params =
|
||||
\"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\" \\
|
||||
\"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\" \\
|
||||
\"BOOST_PFR_DOXYGEN_INVOKED\" \\
|
||||
"
|
||||
<doxygen:param>"PREDEFINED= \\
|
||||
\"BOOST_PFR_DOXYGEN_INVOKED=1\" \\
|
||||
"
|
||||
;
|
||||
|
||||
@@ -52,7 +54,7 @@ boostbook pfr-doc
|
||||
pfr.qbk
|
||||
:
|
||||
<dependency>autodoc_pfr
|
||||
<xsl:param>boost.root=https://www.boost.org/doc/libs/1_72_0
|
||||
<xsl:param>boost.root=https://www.boost.org/doc/libs/1_81_0
|
||||
#<xsl:param>boost.root=../../../.
|
||||
<xml:param>html.stylesheet=../../../../doc/src/boostbook.css
|
||||
;
|
||||
|
||||
63
doc/pfr.qbk
63
doc/pfr.qbk
@@ -1,7 +1,7 @@
|
||||
[library Boost.PFR
|
||||
[quickbook 1.6]
|
||||
[version 2.0]
|
||||
[copyright 2016-2021 Antony Polukhin]
|
||||
[version 2.1]
|
||||
[copyright 2016-2023 Antony Polukhin]
|
||||
[category Language Features Emulation]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
@@ -17,6 +17,7 @@ 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]].
|
||||
|
||||
|
||||
@@ -42,23 +43,23 @@ 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)",
|
||||
std::move(friend_info.id), //////////////////////////////////////////////
|
||||
std::move(friend_info.name), // Users are forced to move individual fields
|
||||
std::move(friend_info.email), // because your library can not iterate over
|
||||
std::move(friend_info.login) // the fields of a user provided structure
|
||||
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
|
||||
);
|
||||
|
||||
return friend_info;
|
||||
@@ -80,22 +81,22 @@ 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 ////////////////////////////////////////////////////////////
|
||||
// Boost.PFR allows you to iterate over all the fields of a
|
||||
// user provided structure
|
||||
friend_info /////////////////////////////////////////////////////////
|
||||
// Boost.PFR allows you to iterate over all the fields
|
||||
// of a user provided structure
|
||||
//
|
||||
);
|
||||
|
||||
@@ -119,7 +120,7 @@ struct user_info {
|
||||
std::string name, email, login;
|
||||
};
|
||||
|
||||
/// Customizations via hand-written code or macro like BOOST_FUSION_ADAPT_STRUCT ///
|
||||
/// Customizations via hand-written code ////////////////////////////////////////
|
||||
auto db_api_tie(user_info& ui) noexcept {
|
||||
return std::tie(ui.id, ui.name, ui.email, ui.login);
|
||||
}
|
||||
@@ -127,7 +128,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);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
```
|
||||
][
|
||||
```
|
||||
@@ -138,7 +139,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 //////////
|
||||
|
||||
|
||||
|
||||
@@ -146,14 +147,29 @@ 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<std::is_aggregate_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 ]
|
||||
@@ -164,12 +180,13 @@ Boost.PFR adds the following out-of-the-box functionality for aggregate initiali
|
||||
* heterogeneous comparators
|
||||
* hash
|
||||
* IO streaming
|
||||
* access to members by index
|
||||
* access to members by index or type
|
||||
* member type retrieval
|
||||
* 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 github] into your project, and the library will work fine.
|
||||
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++17 and above. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
|
||||
|
||||
@@ -467,6 +484,8 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d
|
||||
[[*BOOST_PFR_USE_LOOPHOLE*] [Define to `1` if you wish to override Boost.PFR choice and exploit [@http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118 CWG 2118] for reflection. Define to `0` to override Boost.PFR choice and disable CWG 2118 usage.]]
|
||||
[[*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_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. ]]
|
||||
]
|
||||
|
||||
|
||||
@@ -475,8 +494,8 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d
|
||||
The Boost.PFRs reflection has some limitations that depend on a C++ Standard and compiler capabilities:
|
||||
|
||||
* Static variables are ignored
|
||||
* T must be aggregate initializable without empty base classes
|
||||
* if T contains C arrays or it is inherited from non-empty type then the result of reflection may differ depending on the C++ version and library configuration
|
||||
* T must be aggregate initializable without base classes
|
||||
* if T contains C arrays then the result of reflection may differ depending on the C++ version and library configuration
|
||||
* Additional limitations if [*BOOST_PFR_USE_CPP17 == 0]:
|
||||
* Non of the member fields should have a template constructor from one parameter.
|
||||
* Additional limitations if [*BOOST_PFR_USE_LOOPHOLE == 0]:
|
||||
@@ -518,7 +537,7 @@ Description of the [*BOOST_PFR_USE_LOOPHOLE == 1] technique by its inventor Alex
|
||||
|
||||
[section Acknowledgements]
|
||||
|
||||
Many thanks to Bruno Dutra for showing the technique to precisely reflect aggregate initializable type in C++14 [@https://github.com/apolukhin/magic_get/issues/5 Manual type registering/structured bindings might be unnecessary].
|
||||
Many thanks to Bruno Dutra for showing the technique to precisely reflect aggregate initializable type in C++14 [@https://github.com/boostorg/pfr/issues/5 Manual type registering/structured bindings might be unnecessary].
|
||||
|
||||
Many thanks to Alexandr Poltavsky for initial implementation the [*BOOST_PFR_USE_LOOPHOLE == 1] technique and for describing it [@http://alexpolt.github.io/type-loophole.html in his blog].
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016-2021 Antony Polukhin
|
||||
// Copyright 2016-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016-2021 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 and assign new value to that field
|
||||
// Get field by index/type and assign new value to that field
|
||||
|
||||
struct sample {
|
||||
char c;
|
||||
@@ -100,8 +100,9 @@ void test_examples() {
|
||||
|
||||
sample var{};
|
||||
boost::pfr::get<1>(var) = 42.01f;
|
||||
boost::pfr::get<char>(var) = 'A';
|
||||
|
||||
std::cout << var.f; // Outputs: 42.01
|
||||
std::cout << var.c << var.f; // Outputs: A 42.01
|
||||
//]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016-2021 Antony Polukhin
|
||||
// Copyright 2016-2023 Antony Polukhin
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See the accompanying file LICENSE_1_0.txt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -9,6 +9,7 @@
|
||||
/// \file boost/pfr.hpp
|
||||
/// Includes all the Boost.PFR headers
|
||||
|
||||
#include <boost/pfr/config.hpp>
|
||||
#include <boost/pfr/core.hpp>
|
||||
#include <boost/pfr/functions_for.hpp>
|
||||
#include <boost/pfr/functors.hpp>
|
||||
@@ -17,5 +18,7 @@
|
||||
#include <boost/pfr/ops.hpp>
|
||||
#include <boost/pfr/ops_fields.hpp>
|
||||
#include <boost/pfr/tuple_size.hpp>
|
||||
#include <boost/pfr/traits_fwd.hpp>
|
||||
#include <boost/pfr/traits.hpp>
|
||||
|
||||
#endif // BOOST_PFR_HPP
|
||||
|
||||
121
include/boost/pfr/config.hpp
Normal file
121
include/boost/pfr/config.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2016-2023 Antony Polukhin
|
||||
// Copyright (c) 2022 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_CONFIG_HPP
|
||||
#define BOOST_PFR_CONFIG_HPP
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus >= 201402L || (defined(_MSC_VER) && defined(_MSVC_LANG) && _MSC_VER > 1900)
|
||||
#include <type_traits> // to get non standard platform macro definitions (__GLIBCXX__ for example)
|
||||
#endif
|
||||
|
||||
/// \file boost/pfr/config.hpp
|
||||
/// Contains all the macros that describe Boost.PFR configuration, like BOOST_PFR_ENABLED
|
||||
///
|
||||
/// \note This header file doesn't require C++14 Standard and supports all C++ compilers, even pre C++14 compilers (C++11, C++03...).
|
||||
|
||||
// Reminder:
|
||||
// * MSVC++ 14.2 _MSC_VER == 1927 <- Loophole is known to work (Visual Studio ????)
|
||||
// * MSVC++ 14.1 _MSC_VER == 1916 <- Loophole is known to NOT work (Visual Studio 2017)
|
||||
// * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
|
||||
// * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
|
||||
|
||||
#ifdef BOOST_PFR_NOT_SUPPORTED
|
||||
# error Please, do not set BOOST_PFR_NOT_SUPPORTED value manually, use '-DBOOST_PFR_ENABLED=0' instead of it
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if !defined(_MSVC_LANG) || _MSC_VER <= 1900
|
||||
# define BOOST_PFR_NOT_SUPPORTED 1
|
||||
# endif
|
||||
#elif __cplusplus < 201402L
|
||||
# define BOOST_PFR_NOT_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_LOOPHOLE
|
||||
# if defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1927
|
||||
# define BOOST_PFR_USE_LOOPHOLE 1
|
||||
# else
|
||||
# define BOOST_PFR_USE_LOOPHOLE 0
|
||||
# endif
|
||||
# elif defined(__clang_major__) && __clang_major__ >= 8
|
||||
# define BOOST_PFR_USE_LOOPHOLE 0
|
||||
# else
|
||||
# define BOOST_PFR_USE_LOOPHOLE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_CPP17
|
||||
# ifdef __cpp_structured_bindings
|
||||
# define BOOST_PFR_USE_CPP17 1
|
||||
# elif defined(_MSVC_LANG)
|
||||
# if _MSVC_LANG >= 201703L
|
||||
# define BOOST_PFR_USE_CPP17 1
|
||||
# else
|
||||
# define BOOST_PFR_USE_CPP17 0
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_PFR_USE_CPP17 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (!BOOST_PFR_USE_CPP17 && !BOOST_PFR_USE_LOOPHOLE)
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 1916) ///< in Visual Studio 2017 v15.9 PFR library with classic engine normally works
|
||||
# define BOOST_PFR_NOT_SUPPORTED 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE
|
||||
// Assume that libstdc++ since GCC-7.3 does not have linear instantiation depth in std::make_integral_sequence
|
||||
# if defined( __GLIBCXX__) && __GLIBCXX__ >= 20180101
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1
|
||||
# elif defined(_MSC_VER)
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1
|
||||
//# elif other known working lib
|
||||
# else
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
|
||||
# if defined(__cpp_guaranteed_copy_elision) && (!defined(_MSC_VER) || _MSC_VER > 1928)
|
||||
# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 1
|
||||
# else
|
||||
# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
|
||||
# if defined(__cpp_lib_is_aggregate)
|
||||
# define BOOST_PFR_ENABLE_IMPLICIT_REFLECTION 1
|
||||
# else
|
||||
// There is no way to detect potential ability to be reflectable without std::is_aggregare
|
||||
# define BOOST_PFR_ENABLE_IMPLICIT_REFLECTION 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(maybe_unused)
|
||||
# define BOOST_PFR_MAYBE_UNUSED [[maybe_unused]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_MAYBE_UNUSED
|
||||
# define BOOST_PFR_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_ENABLED
|
||||
# ifdef BOOST_PFR_NOT_SUPPORTED
|
||||
# define BOOST_PFR_ENABLED 0
|
||||
# else
|
||||
# define BOOST_PFR_ENABLED 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#undef BOOST_PFR_NOT_SUPPORTED
|
||||
|
||||
#endif // BOOST_PFR_CONFIG_HPP
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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,20 +30,25 @@
|
||||
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
|
||||
@@ -66,11 +71,45 @@ 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>* = 0) noexcept {
|
||||
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) ));
|
||||
}
|
||||
|
||||
|
||||
/// \brief `tuple_element` has a member typedef `type` that returns the type of a field with index I in \aggregate T.
|
||||
///
|
||||
/// \b Example:
|
||||
@@ -97,7 +136,7 @@ using tuple_element_t = typename tuple_element<I, T>::type;
|
||||
/// \code
|
||||
/// struct my_struct { int i, short s; };
|
||||
/// my_struct s {10, 11};
|
||||
/// std::tuple<int, short> t = make_tuple(s);
|
||||
/// std::tuple<int, short> t = boost::pfr::structure_to_tuple(s);
|
||||
/// assert(get<0>(t) == 10);
|
||||
/// \endcode
|
||||
template <class T>
|
||||
@@ -119,10 +158,10 @@ constexpr auto structure_to_tuple(const T& val) noexcept {
|
||||
/// struct my_struct { int i, short s; };
|
||||
///
|
||||
/// const my_struct const_s{1, 2};
|
||||
/// std::apply(foo, structure_tie(const_s));
|
||||
/// std::apply(foo, boost::pfr::structure_tie(const_s));
|
||||
///
|
||||
/// my_struct s;
|
||||
/// structure_tie(s) = std::tuple<int, short>{10, 11};
|
||||
/// boost::pfr::structure_tie(s) = std::tuple<int, short>{10, 11};
|
||||
/// assert(s.s == 11);
|
||||
/// \endcode
|
||||
template <class T>
|
||||
@@ -159,7 +198,7 @@ constexpr auto structure_tie(T&, std::enable_if_t<!std::is_assignable<T, T>::val
|
||||
|
||||
/// \overload structure_tie
|
||||
template <class T>
|
||||
constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = 0) noexcept {
|
||||
constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&>::value>* = nullptr) noexcept {
|
||||
static_assert(sizeof(T) && false, "====================> Boost.PFR: Calling boost::pfr::structure_tie on rvalue references is forbidden");
|
||||
return 0;
|
||||
}
|
||||
@@ -177,7 +216,7 @@ constexpr auto structure_tie(T&&, std::enable_if_t< std::is_rvalue_reference<T&&
|
||||
/// \code
|
||||
/// struct my_struct { int i, short s; };
|
||||
/// int sum = 0;
|
||||
/// for_each_field(my_struct{20, 22}, [&sum](const auto& field) { sum += field; });
|
||||
/// boost::pfr::for_each_field(my_struct{20, 22}, [&sum](const auto& field) { sum += field; });
|
||||
/// assert(sum == 42);
|
||||
/// \endcode
|
||||
template <class T, class F>
|
||||
@@ -214,7 +253,7 @@ void for_each_field(T&& value, F&& func) {
|
||||
/// return res;
|
||||
/// }
|
||||
/// auto [p, s] = f();
|
||||
/// tie_from_structure(p, s) = f();
|
||||
/// boost::pfr::tie_from_structure(p, s) = f();
|
||||
/// \endcode
|
||||
template <typename... Elements>
|
||||
constexpr detail::tie_from_structure_tuple<Elements...> tie_from_structure(Elements&... args) noexcept {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016-2021 Antony Polukhin
|
||||
// Copyright (c) 2016-2023 Antony Polukhin
|
||||
// Copyright (c) 2022 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)
|
||||
@@ -7,85 +8,19 @@
|
||||
#define BOOST_PFR_DETAIL_CONFIG_HPP
|
||||
#pragma once
|
||||
|
||||
#include <type_traits> // to get non standard platform macro definitions (__GLIBCXX__ for example)
|
||||
#include <boost/pfr/config.hpp>
|
||||
|
||||
// Reminder:
|
||||
// * MSVC++ 14.2 _MSC_VER == 1927 <- Loophole is known to work (Visual Studio ????)
|
||||
// * MSVC++ 14.1 _MSC_VER == 1916 <- Loophole is known to NOT work (Visual Studio 2017)
|
||||
// * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
|
||||
// * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
|
||||
#if !BOOST_PFR_ENABLED
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if !defined(_MSVC_LANG) || _MSC_VER <= 1900
|
||||
# error Boost.PFR library requires more modern MSVC compiler.
|
||||
# endif
|
||||
#elif __cplusplus < 201402L
|
||||
# error Boost.PFR library requires at least C++14.
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_LOOPHOLE
|
||||
# if defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1927
|
||||
# define BOOST_PFR_USE_LOOPHOLE 1
|
||||
# else
|
||||
# define BOOST_PFR_USE_LOOPHOLE 0
|
||||
# endif
|
||||
# elif defined(__clang_major__) && __clang_major__ >= 8
|
||||
# define BOOST_PFR_USE_LOOPHOLE 0
|
||||
# else
|
||||
# define BOOST_PFR_USE_LOOPHOLE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_CPP17
|
||||
# ifdef __cpp_structured_bindings
|
||||
# define BOOST_PFR_USE_CPP17 1
|
||||
# elif defined(_MSVC_LANG)
|
||||
# if _MSVC_LANG >= 201703L
|
||||
# define BOOST_PFR_USE_CPP17 1
|
||||
# else
|
||||
# define BOOST_PFR_USE_CPP17 0
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_PFR_USE_CPP17 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (!BOOST_PFR_USE_CPP17 && !BOOST_PFR_USE_LOOPHOLE)
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 1916) ///< in Visual Studio 2017 v15.9 PFR library with classic engine normally works
|
||||
# error Boost.PFR requires /std:c++latest or /std:c++17 flags on your compiler.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE
|
||||
// Assume that libstdc++ since GCC-7.3 does not have linear instantiation depth in std::make_integral_sequence
|
||||
# if defined( __GLIBCXX__) && __GLIBCXX__ >= 20180101
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1
|
||||
# elif defined(_MSC_VER)
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1
|
||||
//# elif other known working lib
|
||||
# else
|
||||
# define BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_HAS_GUARANTEED_COPY_ELISION
|
||||
# if defined(__cpp_guaranteed_copy_elision) && (!defined(_MSC_VER) || _MSC_VER > 1928)
|
||||
# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 1
|
||||
# else
|
||||
# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(maybe_unused)
|
||||
# define BOOST_PFR_MAYBE_UNUSED [[maybe_unused]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_MAYBE_UNUSED
|
||||
# define BOOST_PFR_MAYBE_UNUSED
|
||||
#endif
|
||||
#error Boost.PFR library is not supported in your environment. \
|
||||
Try one of the possible solutions: \
|
||||
1. try to take away an '-DBOOST_PFR_ENABLED=0', if it exists \
|
||||
2. enable C++14; \
|
||||
3. enable C++17; \
|
||||
4. update your compiler; \
|
||||
or disable this error by '-DBOOST_PFR_ENABLED=1' if you really know what are you doing.
|
||||
|
||||
#endif // !BOOST_PFR_ENABLED
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_CONFIG_HPP
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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;
|
||||
@@ -118,16 +118,16 @@ template <class Type> constexpr std::size_t type_to_id(identity<const Type*>) no
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<const volatile Type*>) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<volatile Type*>) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type&>) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_enum<Type>::value>* = 0) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_empty<Type>::value>* = 0) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_union<Type>::value>* = 0) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_enum<Type>::value>* = nullptr) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_empty<Type>::value>* = nullptr) noexcept;
|
||||
template <class Type> constexpr std::size_t type_to_id(identity<Type>, std::enable_if_t<std::is_union<Type>::value>* = nullptr) noexcept;
|
||||
template <class Type> constexpr size_array<sizeof(Type) * 3> type_to_id(identity<Type>, std::enable_if_t<!std::is_enum<Type>::value && !std::is_empty<Type>::value && !std::is_union<Type>::value>* = 0) noexcept;
|
||||
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_const_ptr_type> = 0) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_ptr_type> = 0) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_const_volatile_ptr_type> = 0) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_volatile_ptr_type> = 0) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_ref_type> = 0) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_const_ptr_type> = nullptr) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_ptr_type> = nullptr) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_const_volatile_ptr_type> = nullptr) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_volatile_ptr_type> = nullptr) noexcept;
|
||||
template <std::size_t Index> constexpr auto id_to_type(size_t_<Index >, if_extension<Index, native_ref_type> = nullptr) noexcept;
|
||||
|
||||
|
||||
///////////////////// Definitions of type_to_id and id_to_type for fundamental types
|
||||
@@ -599,13 +599,20 @@ struct ubiq_constructor_constexpr_copy {
|
||||
/////////////////////
|
||||
|
||||
template <class T, std::size_t... I>
|
||||
struct is_constexpr_aggregate_initializable { // TODO: try to fix it
|
||||
template <T = T{ ubiq_constructor_constexpr_copy{I}... } >
|
||||
struct is_constexpr_aggregate_initializable {
|
||||
template<class T2, std::size_t... I2>
|
||||
static constexpr void* constexpr_aggregate_initializer() noexcept {
|
||||
T2 tmp{ ubiq_constructor_constexpr_copy{I2}... };
|
||||
(void)tmp;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <void* = constexpr_aggregate_initializer<T, I...>() >
|
||||
static std::true_type test(long) noexcept;
|
||||
|
||||
static std::false_type test(...) noexcept;
|
||||
|
||||
static constexpr decltype( test(0) ) value{};
|
||||
static constexpr bool value = decltype(test(0)){};
|
||||
};
|
||||
|
||||
|
||||
@@ -676,16 +683,7 @@ void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
|
||||
!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."
|
||||
);
|
||||
|
||||
/// Compile time error at this point means that you have called `for_each_field` or some other non-flat function or operator for a
|
||||
/// type that is not constexpr aggregate initializable.
|
||||
///
|
||||
/// Make sure that all the fields of your type have constexpr default construtors and trivial destructors.
|
||||
/// Or compile in C++17 mode.
|
||||
constexpr T tmp{ ubiq_constructor_constexpr_copy{I}... };
|
||||
(void)tmp;
|
||||
|
||||
//static_assert(is_constexpr_aggregate_initializable<T, I...>::value, "====================> Boost.PFR: T must be a constexpr initializable type");
|
||||
static_assert(is_constexpr_aggregate_initializable<T, I...>::value, "====================> Boost.PFR: T must be a constexpr initializable type");
|
||||
|
||||
constexpr bool is_flat_refelectable_val = detail::is_flat_refelectable<T>( std::index_sequence<I...>{} );
|
||||
detail::for_each_field_dispatcher_1(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2017-2018 Alexandr Poltavsky, Antony Polukhin.
|
||||
// Copyright (c) 2019-2021 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
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#ifndef BOOST_PFR_DETAIL_CORE14_LOOPHOLE_HPP
|
||||
#define BOOST_PFR_DETAIL_CORE14_LOOPHOLE_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#ifndef BOOST_PFR_DETAIL_CORE17_HPP
|
||||
#define BOOST_PFR_DETAIL_CORE17_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/core17_generated.hpp>
|
||||
#include <boost/pfr/detail/fields_count.hpp>
|
||||
@@ -22,7 +23,7 @@ struct do_not_define_std_tuple_size_for_me {
|
||||
template <class T>
|
||||
constexpr bool do_structured_bindings_work() noexcept { // ******************************************* IN CASE OF ERROR READ THE FOLLOWING LINES IN boost/pfr/detail/core17.hpp FILE:
|
||||
T val{};
|
||||
const auto& [a] = val; // ******************************************* IN CASE OF ERROR READ THE FOLLOWING LINES IN boost/pfr/detail/core17.hpp FILE:
|
||||
auto& [a] = val; // ******************************************* IN CASE OF ERROR READ THE FOLLOWING LINES IN boost/pfr/detail/core17.hpp FILE:
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -295,7 +295,13 @@ constexpr std::size_t fields_count() noexcept {
|
||||
// );
|
||||
//#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1920)
|
||||
// Workaround for msvc compilers. Versions <= 1920 have a limit of max 1024 elements in template parameter pack
|
||||
constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT >= 1024 ? 1024 : sizeof(type) * CHAR_BIT);
|
||||
#else
|
||||
constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT); // We multiply by CHAR_BIT because the type may have bitfields in T
|
||||
#endif
|
||||
|
||||
constexpr std::size_t result = detail::detect_fields_count_dispatch<type>(size_t_<max_fields_count>{}, 1L, 1L);
|
||||
|
||||
detail::assert_first_not_base<type>(detail::make_index_sequence<result>{});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -29,9 +29,10 @@ void for_each_field_impl_apply(T&& v, F&& f, I /*i*/, int) {
|
||||
std::forward<F>(f)(std::forward<T>(v));
|
||||
}
|
||||
|
||||
#if !defined(__cpp_fold_expressions) || __cpp_fold_expressions < 201603
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
|
||||
const int v[] = {(
|
||||
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,12 +42,23 @@ void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
|
||||
const int v[] = {(
|
||||
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
|
||||
)...};
|
||||
(void)v;
|
||||
}
|
||||
#else
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::false_type /*move_values*/) {
|
||||
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(t), std::forward<F>(f), size_t_<I>{}, 1L), ...);
|
||||
}
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_impl(T& t, F&& f, std::index_sequence<I...>, std::true_type /*move_values*/) {
|
||||
(detail::for_each_field_impl_apply(sequence_tuple::get<I>(std::move(t)), std::forward<F>(f), size_t_<I>{}, 1L), ...);
|
||||
}
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2018 Sergei Fedorov
|
||||
// Copyright (c) 2019-2021 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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2017-2018 Chris Beck
|
||||
// Copyright (c) 2019-2021 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)
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <memory> // std::addressof
|
||||
#include <boost/pfr/detail/sequence_tuple.hpp>
|
||||
#include <boost/pfr/detail/rvalue_t.hpp>
|
||||
#include <boost/pfr/detail/size_t_.hpp>
|
||||
|
||||
49
include/boost/pfr/detail/possible_reflectable.hpp
Normal file
49
include/boost/pfr/detail/possible_reflectable.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2022 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_POSSIBLE_REFLECTABLE_HPP
|
||||
#define BOOST_PFR_DETAIL_POSSIBLE_REFLECTABLE_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
#include <boost/pfr/traits_fwd.hpp>
|
||||
|
||||
#include <type_traits> // for std::is_aggregate
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
///////////////////// Returns false when the type exactly wasn't be reflectable
|
||||
template <class T, class WhatFor>
|
||||
constexpr decltype(is_reflectable<T, WhatFor>::value) possible_reflectable(long) noexcept {
|
||||
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)
|
||||
using type = std::remove_cv_t<T>;
|
||||
return std::is_aggregate<type>();
|
||||
# else
|
||||
return true;
|
||||
# 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
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -50,30 +50,74 @@ struct tuple_base<std::index_sequence<> > {
|
||||
|
||||
template <std::size_t N, class T>
|
||||
constexpr T& get_impl(base_from_member<N, T>& t) noexcept {
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
return t.value;
|
||||
}
|
||||
|
||||
template <std::size_t N, class T>
|
||||
constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept {
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
return t.value;
|
||||
}
|
||||
|
||||
template <std::size_t N, class T>
|
||||
constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept {
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
return t.value;
|
||||
}
|
||||
|
||||
template <std::size_t N, class T>
|
||||
constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept {
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
return t.value;
|
||||
}
|
||||
|
||||
template <std::size_t N, class T>
|
||||
constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept {
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
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 {
|
||||
// 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<
|
||||
detail::index_sequence_for<Values...>,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2018 Adam Butcher, Antony Polukhin
|
||||
// Copyright (c) 2019-2021 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)
|
||||
@@ -39,6 +39,6 @@ struct tie_from_structure_tuple : std::tuple<Elements&...> {
|
||||
}
|
||||
};
|
||||
|
||||
}}} // boost::pfr::detail
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_TIE_FROM_STRUCTURE_TUPLE_HPP
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Copyright (c) 2019-2021 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)
|
||||
|
||||
#ifndef BOOST_PFR_DETAIL_UNSAFE_DECLVAL_HPP
|
||||
#define BOOST_PFR_DETAIL_UNSAFE_DECLVAL_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
@@ -24,7 +25,7 @@ template <class T>
|
||||
constexpr T unsafe_declval() noexcept {
|
||||
report_if_you_see_link_error_with_this_function();
|
||||
|
||||
typename std::remove_reference<T>::type* ptr = 0;
|
||||
typename std::remove_reference<T>::type* ptr = nullptr;
|
||||
ptr += 42; // suppresses 'null pointer dereference' warnings
|
||||
return static_cast<T>(*ptr);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -89,17 +89,17 @@ enable_istreamable_t<std::basic_istream<Char, Traits>, T> operator>>(std::basic_
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// IO manupulator to read/write \aggregate `value` using its IO stream operators or using \forcedlink{io_fields} if operators are not awailable.
|
||||
/// IO manipulator to read/write \aggregate `value` using its IO stream operators or using \forcedlink{io_fields} if operators are not available.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct my_struct { int i; short s; };
|
||||
/// my_struct s;
|
||||
/// my_struct x;
|
||||
/// std::stringstream ss;
|
||||
/// ss << "{ 12, 13 }";
|
||||
/// ss >> boost::pfr::io(s);
|
||||
/// assert(s.i == 12);
|
||||
/// assert(s.i == 13);
|
||||
/// ss >> boost::pfr::io(x);
|
||||
/// assert(x.i == 12);
|
||||
/// assert(x.s == 13);
|
||||
/// \endcode
|
||||
///
|
||||
/// \customio
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <boost/pfr/tuple_size.hpp>
|
||||
|
||||
/// \file boost/pfr/io_fields.hpp
|
||||
/// Contains IO manupulator \forcedlink{io_fields} to read/write \aggregate `value` field-by-field.
|
||||
/// Contains IO manipulator \forcedlink{io_fields} to read/write any \aggregate field-by-field.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
@@ -132,7 +132,7 @@ std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& i
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// IO manupulator to read/write \aggregate `value` field-by-field.
|
||||
/// IO manipulator to read/write \aggregate `value` field-by-field.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
|
||||
60
include/boost/pfr/traits.hpp
Normal file
60
include/boost/pfr/traits.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2022 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_TRAITS_HPP
|
||||
#define BOOST_PFR_TRAITS_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
#include <boost/pfr/detail/possible_reflectable.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/// \file boost/pfr/traits.hpp
|
||||
/// Contains traits \forcedlink{is_reflectable} and \forcedlink{is_implicitly_reflectable} for detecting an ability to reflect type.
|
||||
///
|
||||
/// \b Synopsis:
|
||||
|
||||
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.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// namespace boost { namespace pfr {
|
||||
/// template<class All> struct is_reflectable<A, All> : std::false_type {}; // 'A' won't be interpreted as reflectable everywhere
|
||||
/// 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.
|
||||
template<class T, class WhatFor>
|
||||
struct is_reflectable { /* does not have '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
|
||||
template<class T, class WhatFor>
|
||||
struct is_reflectable<const T, WhatFor> : boost::pfr::is_reflectable<T, WhatFor> {};
|
||||
|
||||
template<class T, class WhatFor>
|
||||
struct is_reflectable<volatile T, WhatFor> : boost::pfr::is_reflectable<T, WhatFor> {};
|
||||
|
||||
template<class T, class WhatFor>
|
||||
struct is_reflectable<const volatile T, WhatFor> : boost::pfr::is_reflectable<T, WhatFor> {};
|
||||
|
||||
/// Checks the input type for the potential to be reflected.
|
||||
/// Specialize is_reflectable if you 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.
|
||||
template<class T, class WhatFor>
|
||||
constexpr bool is_implicitly_reflectable_v = is_implicitly_reflectable<T, WhatFor>::value;
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_TRAITS_HPP
|
||||
|
||||
21
include/boost/pfr/traits_fwd.hpp
Normal file
21
include/boost/pfr/traits_fwd.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2022 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_TRAITS_FWD_HPP
|
||||
#define BOOST_PFR_DETAIL_TRAITS_FWD_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
template<class T, class WhatFor>
|
||||
struct is_reflectable;
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_TRAITS_FWD_HPP
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
/// Has a static const member variable `value` that contains fields count in a T.
|
||||
/// Works for any T that supports aggregate initialization.
|
||||
/// Works for any T that satisfies \aggregate.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
@@ -34,7 +34,7 @@ using tuple_size = detail::size_t_< boost::pfr::detail::fields_count<T>() >;
|
||||
|
||||
|
||||
/// `tuple_size_v` is a template variable that contains fields count in a T and
|
||||
/// works for any T that supports aggregate initialization.
|
||||
/// works for any T that satisfies \aggregate.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2014-2021 Antony Polukhin
|
||||
Copyright (c) 2014-2023 Antony Polukhin
|
||||
antoshkka at gmail dot com
|
||||
|
||||
Distributed under the Boost Software License,
|
||||
@@ -29,7 +29,7 @@
|
||||
<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>
|
||||
© 2014-2021 Antony Polukhin
|
||||
© 2014-2023 Antony Polukhin
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2016-2020 Antony Polukhin
|
||||
# Copyright (c) 2016-2023 Antony Polukhin
|
||||
# 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)
|
||||
@@ -12,8 +13,10 @@ import string
|
||||
|
||||
# Skipping some letters that may produce keywords or are hard to read, or shadow template parameters
|
||||
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-2020 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
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -35,6 +38,7 @@ PROLOGUE = """// Copyright (c) 2016-2020 Antony Polukhin
|
||||
|
||||
#include <boost/pfr/detail/sequence_tuple.hpp>
|
||||
#include <boost/pfr/detail/size_t_.hpp>
|
||||
#include <type_traits> // for std::conditional_t, std::is_reference
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
@@ -43,20 +47,43 @@ constexpr auto make_tuple_of_references(Args&&... args) noexcept {
|
||||
return sequence_tuple::tuple<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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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>;
|
||||
return const_cast<output_arg_t>(arg);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr auto tie_as_tuple(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>* = 0) noexcept {
|
||||
auto& [a] = val; // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.
|
||||
return ::boost::pfr::detail::make_tuple_of_references(a);
|
||||
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>* = 0) noexcept {
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -77,6 +104,33 @@ constexpr void tie_as_tuple(T& /*val*/, size_t_<I>) noexcept {
|
||||
|
||||
############################################################################################################################
|
||||
|
||||
def fold_workaround_cast(indexes, divider):
|
||||
WORKAROUND_CAST_TEMPLATE = """
|
||||
detail::workaround_cast<T, decltype({arg})>({arg})
|
||||
"""
|
||||
lines = []
|
||||
div = ''
|
||||
tokens = [x.strip() for x in indexes.split(',')]
|
||||
casts = [WORKAROUND_CAST_TEMPLATE.strip().format(arg=tok)
|
||||
for tok in tokens]
|
||||
for i in range(0, len(casts)):
|
||||
if i%WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE==0:
|
||||
div = ''
|
||||
lines.append('')
|
||||
lines[-1] += div + casts[i]
|
||||
div = ','
|
||||
return divider.join(lines)
|
||||
|
||||
def calc_indexes_count(indexes):
|
||||
tokens = [x.strip() for x in indexes.split(',')]
|
||||
return len(tokens)
|
||||
|
||||
class EmptyLinePrinter:
|
||||
def print_once(self):
|
||||
if not self.printed:
|
||||
print("")
|
||||
self.printed = True
|
||||
printed = False
|
||||
|
||||
indexes = " a"
|
||||
print(PROLOGUE)
|
||||
@@ -92,18 +146,26 @@ for i in range(1, funcs_count):
|
||||
indexes += ascii_letters[i // max_args_on_a_line - 1]
|
||||
indexes += ascii_letters[i % max_args_on_a_line]
|
||||
|
||||
printed_casts = fold_workaround_cast(indexes.strip(), ",\n ")
|
||||
indexes_count = calc_indexes_count(indexes.strip())
|
||||
empty_printer = EmptyLinePrinter()
|
||||
|
||||
print("template <class T>")
|
||||
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() + "] = val; // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
|
||||
print(" return ::boost::pfr::detail::make_tuple_of_references(" + indexes.strip() + ");")
|
||||
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(indexes)
|
||||
print(" ] = val; // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
|
||||
print("")
|
||||
print(" ] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.")
|
||||
empty_printer.print_once()
|
||||
|
||||
if indexes_count < WORKAROUND_CAST_EXPRESSIONS_LIMIT_PER_LINE:
|
||||
print(" return ::boost::pfr::detail::make_tuple_of_references(" + printed_casts + ");")
|
||||
else:
|
||||
empty_printer.print_once()
|
||||
print(" return ::boost::pfr::detail::make_tuple_of_references(")
|
||||
print(indexes)
|
||||
print(" " + printed_casts)
|
||||
print(" );")
|
||||
|
||||
print("}\n")
|
||||
|
||||
64
misc/strip_boost_namespace.sh
Executable file
64
misc/strip_boost_namespace.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2021 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)
|
||||
|
||||
echo "***** Making target path"
|
||||
TARGET_PATH="`dirname \"$0\"`/../../pfr_non_boost"
|
||||
rm -rf ${TARGET_PATH}/*
|
||||
mkdir -p ${TARGET_PATH}
|
||||
TARGET_PATH=`cd "${TARGET_PATH}";pwd`
|
||||
|
||||
SOURCE_PATH="`dirname \"$0\"`/.."
|
||||
SOURCE_PATH=`cd "${SOURCE_PATH}";pwd`
|
||||
|
||||
echo "***** Copying from ${SOURCE_PATH} to ${TARGET_PATH}"
|
||||
cp -rf ${SOURCE_PATH}/* ${TARGET_PATH}
|
||||
|
||||
mv ${TARGET_PATH}/include/boost/* ${TARGET_PATH}/include/
|
||||
rm -rf ${TARGET_PATH}/include/boost
|
||||
rm -rf ${TARGET_PATH}/test
|
||||
rm ${TARGET_PATH}/misc/strip_boost_namespace.sh
|
||||
rm -rf ${TARGET_PATH}/meta
|
||||
|
||||
echo "***** Changing sources"
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's|namespace boost { ||g'
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's|namespace boost {||g'
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's|} // namespace boost::| // namespace |g'
|
||||
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's/::boost::pfr/::pfr/g'
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's/boost::pfr/pfr/g'
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's/BOOST_PFR_/PFR_/g'
|
||||
find ${TARGET_PATH} -type f | xargs sed -i 's|boost/pfr|pfr|g'
|
||||
|
||||
find ${TARGET_PATH}/doc -type f | xargs sed -i 's|boost.pfr.|pfr.|g'
|
||||
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++-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++-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"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
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
|
||||
|
||||
rm a.out || :
|
||||
|
||||
echo "***** Done"
|
||||
9
test/Jamfile
Normal file
9
test/Jamfile
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (C) 2023 Denis Mikhailov
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software License,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
build-project config ;
|
||||
build-project core ;
|
||||
@@ -32,6 +32,10 @@ skip_tags: true
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-9.0
|
||||
ADDRMD: 32
|
||||
CXXSTD: latest # fake
|
||||
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# TOOLSET: msvc # TODO: clang-win ???
|
||||
# ADDRMD: 32,64
|
||||
|
||||
22
test/config/Jamfile.v2
Normal file
22
test/config/Jamfile.v2
Normal file
@@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2023 Denis Mikhailov
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software License,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
import python ;
|
||||
import testing ;
|
||||
import ../../config/checks/config : requires ;
|
||||
|
||||
project
|
||||
: source-location .
|
||||
: requirements
|
||||
<define>BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING=1
|
||||
;
|
||||
|
||||
|
||||
test-suite pfr_tests
|
||||
:
|
||||
[ run print_config.cpp : : : <test-info>always_show_run_output : auto_engine_config ]
|
||||
;
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2016-2021 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/core.hpp>
|
||||
#include <boost/pfr/config.hpp> // inclusion of an another PFR header may fail when BOOST_PFR_ENABLED=0
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -13,6 +13,8 @@ int main() {
|
||||
<< "BOOST_PFR_USE_LOOPHOLE == " << BOOST_PFR_USE_LOOPHOLE << '\n'
|
||||
<< "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_ENABLED == " << BOOST_PFR_ENABLED << '\n'
|
||||
<< "__cplusplus == " << __cplusplus << '\n'
|
||||
#ifdef __cpp_structured_bindings
|
||||
<< "__cpp_structured_bindings == " << __cpp_structured_bindings << '\n'
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2016-2021 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
|
||||
@@ -40,7 +40,7 @@ explicit compiler_supports_loophole ;
|
||||
|
||||
local DISABLE_ON_MSVC = ; #<toolset>msvc:<build>no ;
|
||||
local REQUIRE_LOOPHOLE =
|
||||
[ check-target-builds ../test//compiler_supports_loophole : : <build>no ]
|
||||
[ check-target-builds ../core//compiler_supports_loophole : : <build>no ]
|
||||
;
|
||||
|
||||
local STRUCTURED_BINDING_ENGINE = <define>BOOST_PFR_USE_LOOPHOLE=0 <define>BOOST_PFR_USE_CPP17=1 [ requires cxx17_structured_bindings ] ;
|
||||
@@ -49,10 +49,10 @@ local CLASSIC_ENGINE = <define>BOOST_PFR_USE_LOOPHOLE=0 <define>BOOST_PFR_USE_CP
|
||||
|
||||
test-suite pfr_tests
|
||||
:
|
||||
[ run print_config.cpp : : : <test-info>always_show_run_output : auto_engine_config ]
|
||||
|
||||
[ run offset_based_getter.cpp ]
|
||||
|
||||
[ run can_be_as_fallback_in_the_fusion.cpp ]
|
||||
|
||||
[ run test_tuple_sizes_on.cpp : : : <define>BOOST_PFR_RUN_TEST_ON=char : test_tuple_sizes_on_chars ]
|
||||
[ run test_tuple_sizes_on.cpp : : : <define>BOOST_PFR_RUN_TEST_ON=int : test_tuple_sizes_on_ints ]
|
||||
[ run test_tuple_sizes_on.cpp : : : <define>BOOST_PFR_RUN_TEST_ON=short : test_tuple_sizes_on_shorts ]
|
||||
@@ -60,9 +60,9 @@ test-suite pfr_tests
|
||||
[ run test_tuple_sizes_on.cpp : : : <define>BOOST_PFR_RUN_TEST_ON="std::size_t" : test_tuple_sizes_on_size_ts ]
|
||||
|
||||
[ run run/motivating_example.cpp : : : : auto_engine_motivating ]
|
||||
[ run ../example/sample_printing.cpp : : : : auto_engine_sample_printing ]
|
||||
[ run ../example/get.cpp : : : : auto_engine_get ]
|
||||
[ run ../example/quick_examples.cpp : : : : auto_engine_quick ]
|
||||
[ run ../../example/sample_printing.cpp : : : : auto_engine_sample_printing ]
|
||||
[ run ../../example/get.cpp : : : : auto_engine_get ]
|
||||
[ run ../../example/quick_examples.cpp : : : : auto_engine_quick ]
|
||||
;
|
||||
|
||||
local BLACKLIST_TESTS_FOR_LOOPHOLE =
|
||||
@@ -95,7 +95,7 @@ local BLACKLIST_TESTS_FOR_CLASSIC =
|
||||
tie_anonymous_const_field
|
||||
;
|
||||
|
||||
for local source_file in [ glob ./run/*.cpp ] [ glob ../example/*.cpp ]
|
||||
for local source_file in [ glob ./run/*.cpp ] [ glob ../../example/*.cpp ]
|
||||
{
|
||||
local target_name = $(source_file[1]:B) ;
|
||||
pfr_tests += [ run $(source_file) : : : $(STRUCTURED_BINDING_ENGINE) : $(target_name)_sb ] ;
|
||||
@@ -129,5 +129,5 @@ for local source_file in [ glob ./compile-fail/*.cpp ]
|
||||
|
||||
if [ python.configured ]
|
||||
{
|
||||
testing.make-test run-pyd : ../misc/generate_cpp17.py ;
|
||||
testing.make-test run-pyd : ../../misc/generate_cpp17.py ;
|
||||
}
|
||||
37
test/core/can_be_as_fallback_in_the_fusion.cpp
Normal file
37
test/core/can_be_as_fallback_in_the_fusion.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2022 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)
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
struct Aggregate {};
|
||||
using NonAggregate = int;
|
||||
|
||||
template<class T>
|
||||
struct is_implicitly_reflectable : std::false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_implicitly_reflectable<Aggregate> : std::true_type
|
||||
{};
|
||||
|
||||
template<class T, class E=void>
|
||||
struct tag_of_fallback {
|
||||
using type = int; // unknown
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct tag_of_fallback<T, std::enable_if_t<std::is_same<T,T>::value>>
|
||||
{
|
||||
using type = std::conditional_t<
|
||||
is_implicitly_reflectable<T>::value
|
||||
, std::true_type
|
||||
, std::false_type
|
||||
>;
|
||||
};
|
||||
|
||||
static_assert(tag_of_fallback<Aggregate>::type::value == true, "");
|
||||
static_assert(tag_of_fallback<NonAggregate>::type::value == false, "");
|
||||
|
||||
int main() { }
|
||||
10
test/core/compile-fail/boost_pfr_disabled_via_macro.cpp
Normal file
10
test/core/compile-fail/boost_pfr_disabled_via_macro.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2022 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)
|
||||
|
||||
#define BOOST_PFR_ENABLED 0
|
||||
#include <boost/pfr/core.hpp>
|
||||
|
||||
int main() { }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 Antony Polukhin
|
||||
// Copyright (c) 2020-2023 Antony Polukhin
|
||||
// Copyright (c) 2020 Richard Hodges
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 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)
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2019 Ilya Kiselev
|
||||
// Copyright (c) 2019-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
125
test/core/run/core17_generated.cpp
Normal file
125
test/core/run/core17_generated.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/pfr/core.hpp>
|
||||
#include <type_traits> // for std::is_same
|
||||
|
||||
struct A {
|
||||
const volatile int cv_value = 0;
|
||||
volatile int v_value = 0;
|
||||
const int c_value = 0;
|
||||
int value = 0;
|
||||
|
||||
const volatile int& cv_ref;
|
||||
volatile int& v_ref;
|
||||
const int& c_ref;
|
||||
int& ref;
|
||||
|
||||
const volatile int&& cv_rref;
|
||||
volatile int&& v_rref;
|
||||
const int&& c_rref;
|
||||
int&& rref;
|
||||
};
|
||||
|
||||
int main() {
|
||||
#if BOOST_PFR_USE_CPP17
|
||||
const volatile int cv_value = 0;
|
||||
volatile int v_value = 0;
|
||||
const int c_value = 0;
|
||||
int value = 0;
|
||||
|
||||
typedef boost::pfr::detail::size_t_<12> fields_count_tag;
|
||||
|
||||
{
|
||||
A a {cv_value, v_value, c_value, value,
|
||||
cv_value, v_value, c_value, value,
|
||||
std::move(cv_value), std::move(v_value), std::move(c_value), std::move(value)};
|
||||
|
||||
const auto t = boost::pfr::detail::tie_as_tuple(a, fields_count_tag{});
|
||||
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<0>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<1>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<2>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<3>(t)), int&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<4>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<5>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<6>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<7>(t)), int&>());
|
||||
// FIXME implement rvalue references as a field support
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<8>(t)), int const volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<9>(t)), int volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<10>(t)), int const&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<11>(t)), int&&>());
|
||||
}
|
||||
|
||||
{
|
||||
const A a {cv_value, v_value, c_value, value,
|
||||
cv_value, v_value, c_value, value,
|
||||
std::move(cv_value), std::move(v_value), std::move(c_value), std::move(value)};
|
||||
|
||||
const auto t = boost::pfr::detail::tie_as_tuple(a, fields_count_tag{});
|
||||
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<0>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<1>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<2>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<3>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<4>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<5>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<6>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<7>(t)), int&>());
|
||||
// FIXME implement rvalue references as a field support
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<8>(t)), int const volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<9>(t)), int volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<10>(t)), int const&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<11>(t)), int&&>());
|
||||
}
|
||||
|
||||
{
|
||||
volatile A a {cv_value, v_value, c_value, value,
|
||||
cv_value, v_value, c_value, value,
|
||||
std::move(cv_value), std::move(v_value), std::move(c_value), std::move(value)};
|
||||
|
||||
const auto t = boost::pfr::detail::tie_as_tuple(a, fields_count_tag{});
|
||||
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<0>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<1>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<2>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<3>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<4>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<5>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<6>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<7>(t)), int&>());
|
||||
// FIXME implement rvalue references as a field support
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<8>(t)), int const volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<9>(t)), int volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<10>(t)), int const&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<11>(t)), int&&>());
|
||||
}
|
||||
|
||||
{
|
||||
const volatile A a {cv_value, v_value, c_value, value,
|
||||
cv_value, v_value, c_value, value,
|
||||
std::move(cv_value), std::move(v_value), std::move(c_value), std::move(value)};
|
||||
|
||||
const auto t = boost::pfr::detail::tie_as_tuple(a, fields_count_tag{});
|
||||
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<0>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<1>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<2>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<3>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<4>(t)), int const volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<5>(t)), int volatile&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<6>(t)), int const&>());
|
||||
static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<7>(t)), int&>());
|
||||
// FIXME implement rvalue references as a field support
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<8>(t)), int const volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<9>(t)), int volatile&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<10>(t)), int const&&>());
|
||||
// static_assert(std::is_same<decltype(boost::pfr::detail::sequence_tuple::get<11>(t)), int&&>());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2018 Adam Butcher, Antony Polukhin
|
||||
// Copyright (c) 2019-2021 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)
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
|
||||
// Example from https://github.com/apolukhin/magic_get/issues/21
|
||||
// Example from https://github.com/boostorg/pfr/issues/21
|
||||
|
||||
|
||||
// boost::pfr::for_each_field crashes when sizeof(MyConfig) > 248 (probably >= 256)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -54,6 +54,8 @@ struct simple {
|
||||
short d;
|
||||
};
|
||||
|
||||
struct empty{};
|
||||
|
||||
|
||||
int main () {
|
||||
std::size_t control = 0;
|
||||
@@ -108,6 +110,13 @@ int main () {
|
||||
ss << val << ' ';
|
||||
});
|
||||
BOOST_TEST_EQ("42 a 3 ", ss.str());
|
||||
ss.str("");
|
||||
|
||||
boost::pfr::for_each_field(empty{}, [&ss](auto&& val) {
|
||||
ss << val << ' ';
|
||||
});
|
||||
BOOST_TEST_EQ("", ss.str());
|
||||
ss.str("");
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
67
test/core/run/get_by_type.cpp
Normal file
67
test/core/run/get_by_type.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// 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)
|
||||
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 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)
|
||||
83
test/core/run/is_implicitly_reflectable.cpp
Normal file
83
test/core/run/is_implicitly_reflectable.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2022 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)
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/pfr/traits.hpp>
|
||||
#include <type_traits> // for std::true_type, std::false_type and std::is_aggregate
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
struct boost_fusion_tag;
|
||||
struct boost_json_tag;
|
||||
}}
|
||||
|
||||
struct Aggregate {};
|
||||
using Nonaggregate = int;
|
||||
|
||||
#if defined(__cpp_lib_is_aggregate)
|
||||
static_assert(std::is_aggregate<Aggregate>::value && !std::is_aggregate<Nonaggregate>::value, "");
|
||||
#endif
|
||||
|
||||
using Reflectable = short;
|
||||
struct Nonrefrectable {};
|
||||
|
||||
using ReflectableBoostFusion = short;
|
||||
struct NonrefrectableBoostFusion {};
|
||||
|
||||
using ReflectableBoostJson = short;
|
||||
struct NonrefrectableBoostJson {};
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
template<class All> struct is_reflectable<Reflectable, All> : std::true_type {};
|
||||
template<class All> struct is_reflectable<Nonrefrectable, All> : std::false_type {};
|
||||
template<> struct is_reflectable<ReflectableBoostFusion, boost_fusion_tag> : std::true_type {};
|
||||
template<> struct is_reflectable<NonrefrectableBoostFusion, boost_fusion_tag> : std::false_type {};
|
||||
template<> struct is_reflectable<ReflectableBoostJson, boost_json_tag> : std::true_type {};
|
||||
template<> struct is_reflectable<NonrefrectableBoostJson, boost_json_tag> : std::false_type {};
|
||||
}}
|
||||
|
||||
|
||||
#if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
|
||||
template<class T, class Tag>
|
||||
void assert_reflectable() {
|
||||
static_assert(boost::pfr::is_implicitly_reflectable_v<T, Tag>, "");
|
||||
static_assert(boost::pfr::is_implicitly_reflectable_v<const T, Tag>, "");
|
||||
static_assert(boost::pfr::is_implicitly_reflectable_v<volatile T, Tag>, "");
|
||||
static_assert(boost::pfr::is_implicitly_reflectable_v<const volatile T, Tag>, "");
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_non_reflectable() {
|
||||
static_assert(!boost::pfr::is_implicitly_reflectable_v<T, Tag>, "");
|
||||
static_assert(!boost::pfr::is_implicitly_reflectable_v<const T, Tag>, "");
|
||||
static_assert(!boost::pfr::is_implicitly_reflectable_v<volatile T, Tag>, "");
|
||||
static_assert(!boost::pfr::is_implicitly_reflectable_v<const volatile T, Tag>, "");
|
||||
}
|
||||
#endif // #if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
|
||||
|
||||
int main() {
|
||||
#if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
|
||||
std::cout << "Implicit reflection is available in this platform.." << std::endl;
|
||||
{
|
||||
using tag = boost::pfr::boost_json_tag;
|
||||
assert_reflectable<Aggregate, tag>();
|
||||
assert_non_reflectable<Nonaggregate, tag>();
|
||||
assert_reflectable<Reflectable, tag>();
|
||||
assert_non_reflectable<Nonrefrectable, tag>();
|
||||
assert_reflectable<ReflectableBoostJson, tag>();
|
||||
assert_non_reflectable<NonrefrectableBoostJson, tag>();
|
||||
}
|
||||
|
||||
{
|
||||
using tag = boost::pfr::boost_fusion_tag;
|
||||
assert_reflectable<Aggregate, tag>();
|
||||
assert_non_reflectable<Nonaggregate, tag>();
|
||||
assert_reflectable<Reflectable, tag>();
|
||||
assert_non_reflectable<Nonrefrectable, tag>();
|
||||
assert_reflectable<ReflectableBoostFusion, tag>();
|
||||
assert_non_reflectable<NonrefrectableBoostFusion, tag>();
|
||||
}
|
||||
#endif // #if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
|
||||
}
|
||||
|
||||
112
test/core/run/is_reflectable.cpp
Normal file
112
test/core/run/is_reflectable.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) 2022 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)
|
||||
|
||||
#include <boost/pfr/traits.hpp>
|
||||
#include <type_traits> // for std::true_type, std::false_type
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
struct boost_fusion_tag;
|
||||
struct boost_json_tag;
|
||||
}}
|
||||
|
||||
struct Reflectable {};
|
||||
struct Nonrefrectable {};
|
||||
struct Unknown {};
|
||||
|
||||
struct ReflectableBoostFusion {};
|
||||
struct NonrefrectableBoostFusion {};
|
||||
|
||||
struct ReflectableBoostJson {};
|
||||
struct NonrefrectableBoostJson {};
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
template<class All> struct is_reflectable<Reflectable, All> : std::true_type {};
|
||||
template<class All> struct is_reflectable<Nonrefrectable, All> : std::false_type {};
|
||||
template<> struct is_reflectable<ReflectableBoostFusion, boost_fusion_tag> : std::true_type {};
|
||||
template<> struct is_reflectable<NonrefrectableBoostFusion, boost_fusion_tag> : std::false_type {};
|
||||
template<> struct is_reflectable<ReflectableBoostJson, boost_json_tag> : std::true_type {};
|
||||
template<> struct is_reflectable<NonrefrectableBoostJson, boost_json_tag> : std::false_type {};
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace helpers {
|
||||
template <class T, class Tag>
|
||||
constexpr decltype(boost::pfr::is_reflectable<T, Tag>::value) is_reflectability_known(long) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class Tag>
|
||||
constexpr bool is_reflectability_known(int) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_reflectable_impl() {
|
||||
static_assert(helpers::is_reflectability_known<T, Tag>(1L), "");
|
||||
static_assert(boost::pfr::is_reflectable<T, Tag>::value, "");
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_non_reflectable_impl() {
|
||||
static_assert(helpers::is_reflectability_known<T, Tag>(1L), "");
|
||||
static_assert(!boost::pfr::is_reflectable<T, Tag>::value, "");
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_unknown_impl() {
|
||||
static_assert(!helpers::is_reflectability_known<T, Tag>(1L), "");
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_reflectable() {
|
||||
assert_reflectable_impl<T, Tag>();
|
||||
assert_reflectable_impl<const T, Tag>();
|
||||
assert_reflectable_impl<volatile T, Tag>();
|
||||
assert_reflectable_impl<const volatile T, Tag>();
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_non_reflectable() {
|
||||
assert_non_reflectable_impl<T, Tag>();
|
||||
assert_non_reflectable_impl<const T, Tag>();
|
||||
assert_non_reflectable_impl<volatile T, Tag>();
|
||||
assert_non_reflectable_impl<const volatile T, Tag>();
|
||||
}
|
||||
|
||||
template<class T, class Tag>
|
||||
void assert_unknown() {
|
||||
assert_unknown_impl<T, Tag>();
|
||||
assert_unknown_impl<const T, Tag>();
|
||||
assert_unknown_impl<volatile T, Tag>();
|
||||
assert_unknown_impl<const volatile T, Tag>();
|
||||
}
|
||||
|
||||
int main() {
|
||||
{
|
||||
using tag = boost::pfr::boost_json_tag;
|
||||
assert_reflectable<Reflectable, tag>();
|
||||
assert_non_reflectable<Nonrefrectable, tag>();
|
||||
assert_unknown<Unknown, tag>();
|
||||
assert_unknown<ReflectableBoostFusion, tag>();
|
||||
assert_unknown<NonrefrectableBoostFusion, tag>();
|
||||
assert_reflectable<ReflectableBoostJson, tag>();
|
||||
assert_non_reflectable<NonrefrectableBoostJson, tag>();
|
||||
}
|
||||
|
||||
{
|
||||
using tag = boost::pfr::boost_fusion_tag;
|
||||
assert_reflectable<Reflectable, tag>();
|
||||
assert_non_reflectable<Nonrefrectable, tag>();
|
||||
assert_unknown<Unknown, tag>();
|
||||
assert_reflectable<ReflectableBoostFusion, tag>();
|
||||
assert_non_reflectable<NonrefrectableBoostFusion, tag>();
|
||||
assert_unknown<ReflectableBoostJson, tag>();
|
||||
assert_unknown<NonrefrectableBoostJson, tag>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
|
||||
// Test case for https://github.com/apolukhin/magic_get/issues/30
|
||||
// Test case for https://github.com/boostorg/pfr/issues/30
|
||||
|
||||
#include <memory>
|
||||
#include <boost/pfr.hpp>
|
||||
@@ -1,11 +1,12 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
|
||||
// Test case for https://github.com/apolukhin/magic_get/issues/33
|
||||
// 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>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2018-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2021 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)
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019-2021 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)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user