mirror of
https://github.com/boostorg/describe.git
synced 2026-01-20 04:22:34 +00:00
Compare commits
41 Commits
feature/de
...
feature/op
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6bf0c4f1e | ||
|
|
c156466e2b | ||
|
|
9273e7c0af | ||
|
|
ef9c38f90c | ||
|
|
6749a0f46a | ||
|
|
c8c46bfdf7 | ||
|
|
ccfed27ddd | ||
|
|
21de045f39 | ||
|
|
4b65c35009 | ||
|
|
574c1736a3 | ||
|
|
c0fd54e1f7 | ||
|
|
2a50e32645 | ||
|
|
71c9a5100e | ||
|
|
1614c16be7 | ||
|
|
dd950f77fe | ||
|
|
0be3b2833d | ||
|
|
3ac03da76f | ||
|
|
0eb2c9eb25 | ||
|
|
4ccae397a7 | ||
|
|
dae1e8246a | ||
|
|
8d10118745 | ||
|
|
74089b76c3 | ||
|
|
d64c9fb141 | ||
|
|
abc8b0236d | ||
|
|
dd76e316d3 | ||
|
|
acf2e56c34 | ||
|
|
811003ea0c | ||
|
|
bd8be41591 | ||
|
|
f9477bc177 | ||
|
|
d98f4d1f40 | ||
|
|
2e3b6a6791 | ||
|
|
fabf5c7115 | ||
|
|
ec7aec2b3d | ||
|
|
fc458d48c7 | ||
|
|
6cc4ddafd7 | ||
|
|
ed1175b33a | ||
|
|
d4ebe0943e | ||
|
|
1fa144623d | ||
|
|
5032f55ac1 | ||
|
|
71bfb07be2 | ||
|
|
fc15f03c34 |
199
.github/workflows/ci.yml
vendored
199
.github/workflows/ci.yml
vendored
@@ -47,6 +47,10 @@ jobs:
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-11
|
||||
- toolset: gcc-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: g++-12
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
@@ -97,9 +101,19 @@ jobs:
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: clang-12
|
||||
- toolset: clang
|
||||
compiler: clang++-13
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-13
|
||||
- toolset: clang
|
||||
compiler: clang++-14
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-14
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
os: macos-11
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -148,28 +162,32 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.1
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2016
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,latest"
|
||||
- toolset: msvc-14.0
|
||||
cxxstd: "14,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,latest"
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
cxxflags: "-Zc:preprocessor"
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.3
|
||||
cxxstd: "14,17,latest"
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: msvc-14.3
|
||||
cxxstd: "14,17,latest"
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
cxxflags: "-Zc:preprocessor"
|
||||
os: windows-2022
|
||||
- toolset: clang-win
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2022
|
||||
- toolset: gcc
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
addrmd: 64
|
||||
@@ -207,4 +225,163 @@ jobs:
|
||||
run: |
|
||||
cd ../boost-root
|
||||
if not "${{matrix.cxxflags}}" == "" set CXXFLAGS=cxxflags=${{matrix.cxxflags}}
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} %CXXFLAGS% variant=debug,release
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} %CXXFLAGS% variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Use library with add_subdirectory
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install
|
||||
|
||||
- name: Use the installed library
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
@@ -9,7 +9,7 @@ for more information and usage examples.
|
||||
|
||||
* GCC 5 or later with `-std=c++14` or above
|
||||
* Clang 3.9 or later with `-std=c++14` or above
|
||||
* Visual Studio 2015, 2017, 2019
|
||||
* Visual Studio 2015 or later
|
||||
|
||||
Tested on [Github Actions](https://github.com/boostorg/describe/actions) and
|
||||
[Appveyor](https://ci.appveyor.com/project/pdimov/describe).
|
||||
|
||||
18
appveyor.yml
18
appveyor.yml
@@ -1,4 +1,4 @@
|
||||
# Copyright 2016-2020 Peter Dimov
|
||||
# Copyright 2016-2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -15,27 +15,19 @@ branches:
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-14.0
|
||||
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||
ADDRMD: 32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-12.0,msvc-14.0
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
CXXSTD: 14,17
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: clang-win
|
||||
CXXSTD: 14,17,latest
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: msvc-14.2
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: clang-win
|
||||
CXXSTD: 14,17,latest
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: msvc-14.2
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
CXXFLAGS: -Zc:preprocessor
|
||||
|
||||
install:
|
||||
- set BOOST_BRANCH=develop
|
||||
|
||||
@@ -8,9 +8,17 @@ https://www.boost.org/LICENSE_1_0.txt
|
||||
# Revision History
|
||||
:idprefix:
|
||||
|
||||
## Changes in Boost 1.79.0
|
||||
|
||||
* Enabled unions in `BOOST_DESCRIBE_STRUCT` and updated examples to check `std::is_union<T>`.
|
||||
* Added example of defining a `fmtlib` class formatter.
|
||||
* Added example of defining a `fmtlib` enum formatter.
|
||||
* Added example of printing pointers to members.
|
||||
|
||||
## Changes in Boost 1.78.0
|
||||
|
||||
* Added `has_describe_enumerators`, `has_describe_bases`, `has_describe_members`.
|
||||
* Added `enum_to_string`, `enum_from_string`.
|
||||
* Added relational and stream insertion operators.
|
||||
* Added `descriptor_by_name`, `descriptor_by_pointer`.
|
||||
* Added `struct_to_tuple` example.
|
||||
|
||||
@@ -19,6 +19,15 @@ descriptors using `mp11::mp_for_each` and prints them.
|
||||
include::../../example/printing_enums_ct.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
v1: 11
|
||||
v2: 12
|
||||
v3: 5
|
||||
----
|
||||
|
||||
[#example_printing_enums_rt]
|
||||
## Printing Enumerators with a Run Time Loop
|
||||
|
||||
@@ -31,6 +40,18 @@ an ordinary `for` loop, instead of `mp_for_each`.
|
||||
include::../../example/printing_enums_rt.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
v1: 0
|
||||
v2: 1
|
||||
v3: 2
|
||||
v4: 3
|
||||
v5: 4
|
||||
v6: 5
|
||||
----
|
||||
|
||||
[#example_enum_to_string]
|
||||
## enum_to_string
|
||||
|
||||
@@ -43,6 +64,14 @@ to a named value, the function returns `"(unnamed)"`.
|
||||
include::../../example/enum_to_string.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
E(3): v1
|
||||
E(0): (unnamed)
|
||||
----
|
||||
|
||||
Since release 1.78.0, the library provides `enum_to_string`.
|
||||
It differs from the one in the example by having a second
|
||||
parameter that determines what should be returned when the
|
||||
@@ -60,6 +89,16 @@ does not correspond to any enumerator name, throws an exception.
|
||||
include::../../example/string_to_enum.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
v1: 0
|
||||
v2: 1
|
||||
v3: 2
|
||||
v4: Invalid enumerator name 'v4' for enum type 'enum E'
|
||||
----
|
||||
|
||||
Since release 1.78.0, the library provides `enum_from_string`.
|
||||
It differs from the function in the example by signaling failure
|
||||
by a `bool` return value instead of using exceptions. The
|
||||
@@ -85,6 +124,13 @@ change its state and hence cannot violate its invariant.)
|
||||
include::../../example/print_function.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
{{.m1 = 1}, {.m2 = 2}, .m1 = 3, .m2 = 4}
|
||||
----
|
||||
|
||||
Since release 1.78.0, this universal `operator<<` is supplied
|
||||
by the library, in the `boost::describe::operators` namespace.
|
||||
It's enabled by means of a using declaration in the namespace
|
||||
@@ -122,6 +168,13 @@ to all annotated classes also defined in `app`.
|
||||
include::../../example/hash_value.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
12526671134390370097
|
||||
----
|
||||
|
||||
[#example_equality]
|
||||
## Implementing operator==
|
||||
|
||||
@@ -137,6 +190,13 @@ to all annotated classes also defined in `app`.
|
||||
include::../../example/equality.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
true false
|
||||
----
|
||||
|
||||
Since release 1.78.0, this universal `operator==` is supplied
|
||||
by the library, in the `boost::describe::operators` namespace.
|
||||
It's enabled by means of a using declaration in the namespace
|
||||
@@ -161,6 +221,25 @@ using boost::describe::operators::operator==;
|
||||
The rest of the relational operators are also provided and can
|
||||
be enabled similarly.
|
||||
|
||||
[#example_struct_to_tuple]
|
||||
## struct_to_tuple
|
||||
|
||||
This example defines a function `struct_to_tuple` that takes
|
||||
a described class type as an argument and returns a tuple of
|
||||
all its public members.
|
||||
|
||||
[source]
|
||||
----
|
||||
include::../../example/struct_to_tuple.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
std::tuple<int, float>: 1, 3.14
|
||||
----
|
||||
|
||||
[#example_to_json]
|
||||
## Automatic Conversion to JSON
|
||||
|
||||
@@ -182,6 +261,13 @@ disabled in this case using `std::enable_if_t`.
|
||||
include::../../example/to_json.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
{"v":[{"x":1,"y":2},{"x":3,"y":4}],"m":{"k1":{"x":5,"y":6},"k2":{"x":7,"y":8}}}
|
||||
----
|
||||
|
||||
[#example_from_json]
|
||||
## Automatic Conversion from JSON
|
||||
|
||||
@@ -194,6 +280,14 @@ an annotated struct.
|
||||
include::../../example/from_json.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
jv: {"x":1,"y":2}
|
||||
a: { 1, 2 }
|
||||
----
|
||||
|
||||
[#example_serialization]
|
||||
## Automatic Serialization
|
||||
|
||||
@@ -206,6 +300,49 @@ support to annotated classes.
|
||||
include::../../example/serialization.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<!DOCTYPE boost_serialization>
|
||||
<boost_serialization signature="serialization::archive" version="19">
|
||||
<c1 class_id="0" tracking_level="0" version="0">
|
||||
<v class_id="1" tracking_level="0" version="0">
|
||||
<count>3</count>
|
||||
<item_version>0</item_version>
|
||||
<item class_id="2" tracking_level="0" version="0">
|
||||
<base.1 class_id="3" tracking_level="0" version="0">
|
||||
<x>1</x>
|
||||
</base.1>
|
||||
<base.2 class_id="4" tracking_level="0" version="0">
|
||||
<y>2</y>
|
||||
</base.2>
|
||||
</item>
|
||||
<item>
|
||||
<base.1>
|
||||
<x>3</x>
|
||||
</base.1>
|
||||
<base.2>
|
||||
<y>4</y>
|
||||
</base.2>
|
||||
</item>
|
||||
<item>
|
||||
<base.1>
|
||||
<x>5</x>
|
||||
</base.1>
|
||||
<base.2>
|
||||
<y>6</y>
|
||||
</base.2>
|
||||
</item>
|
||||
</v>
|
||||
</c1>
|
||||
</boost_serialization>
|
||||
|
||||
|
||||
22 serialization::archive 19 0 0 0 0 3 0 0 0 0 0 1 0 0 2 3 4 5 6
|
||||
----
|
||||
|
||||
[#example_json_rpc]
|
||||
## Automatic JSON RPC
|
||||
|
||||
@@ -219,6 +356,14 @@ in a `boost::json::value`.
|
||||
include::../../example/json_rpc.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
"Hello, world!"
|
||||
3
|
||||
----
|
||||
|
||||
[#example_console]
|
||||
## Interactive Variable Console
|
||||
|
||||
@@ -230,3 +375,120 @@ for converting the variables to and from a string form.
|
||||
----
|
||||
include::../../example/console.cpp[lines=9..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
|
||||
> help
|
||||
"Enter a variable name ('x', 'y', 'v', or 'm') to print its value; enter variable=value to assign a new value to a variable. Values are in JSON format."
|
||||
|
||||
> x
|
||||
1
|
||||
|
||||
> y
|
||||
3.14E0
|
||||
|
||||
> v
|
||||
[1,2,3]
|
||||
|
||||
> m
|
||||
{"BTC":4.489868E4,"ETH":1.38657E3}
|
||||
|
||||
> x="hello"
|
||||
Error: not a number [boost.json:15]
|
||||
|
||||
> x=3.14
|
||||
Error: not exact [boost.json:16]
|
||||
|
||||
> x=4
|
||||
|
||||
> x
|
||||
4
|
||||
|
||||
> y=6.28
|
||||
|
||||
> y
|
||||
6.28E0
|
||||
|
||||
> v=["hello", "world"]
|
||||
Error: not a number [boost.json:15]
|
||||
|
||||
> v=[1.2, 3.4]
|
||||
Error: not exact [boost.json:16]
|
||||
|
||||
> v=[11, 27]
|
||||
|
||||
> c
|
||||
Error: 'c': no such variable
|
||||
|
||||
> v
|
||||
[11,27]
|
||||
|
||||
> m={"BTC": 42139.07, "ETH": 2912.00}
|
||||
|
||||
> m
|
||||
{"BTC":4.213907E4,"ETH":2.912E3}
|
||||
----
|
||||
|
||||
[#example_fmtlib_class_formatter]
|
||||
## `fmtlib` Class Formatter
|
||||
|
||||
This example defines a universal https://github.com/fmtlib/fmt[`fmtlib`]
|
||||
formatter that works on any class or struct type that has been described
|
||||
with `BOOST_DESCRIBE_STRUCT` or `BOOST_DESCRIBE_CLASS`. It's similar to
|
||||
<<example_print_function,the universal print function shown above>>.
|
||||
|
||||
[source]
|
||||
----
|
||||
include::../../example/fmtlib_class_formatter.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
{ { .r=255, .g=192, .b=16 }, .first={ .x=1, .y=2 }, .last={ .x=3, .y=4 } }
|
||||
----
|
||||
|
||||
[#example_fmtlib_enum_formatter]
|
||||
## `fmtlib` Enum Formatter
|
||||
|
||||
This example defines a https://github.com/fmtlib/fmt[`fmtlib`] formatter
|
||||
for described enums.
|
||||
|
||||
[source]
|
||||
----
|
||||
include::../../example/fmtlib_enum_formatter.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
____v1____
|
||||
____7_____
|
||||
----
|
||||
|
||||
[#example_pm_to_string]
|
||||
## Printing Pointers to Members
|
||||
|
||||
This example defines an `operator<<` overload for pointers to members.
|
||||
|
||||
[source]
|
||||
----
|
||||
include::../../example/pm_to_string.cpp[lines=9..-1]
|
||||
----
|
||||
|
||||
Sample output:
|
||||
|
||||
[listing]
|
||||
----
|
||||
&X::m [int]
|
||||
&X::f [int() const]
|
||||
&Y::m [int]
|
||||
&X::f [int() const]
|
||||
&Y::g [int() const]
|
||||
&Z::(unknown) [void()]
|
||||
----
|
||||
|
||||
@@ -16,7 +16,7 @@ https://boost.org/libs/mp11[Boost.Mp11].
|
||||
|
||||
* GCC 5 or later with `-std=c++14` or above
|
||||
* Clang 3.9 or later with `-std=c++14` or above
|
||||
* Visual Studio 2015, 2017, 2019
|
||||
* Visual Studio 2015 or later
|
||||
|
||||
Tested on https://github.com/boostorg/describe/actions[Github Actions]
|
||||
and https://ci.appveyor.com/project/pdimov/describe[Appveyor].
|
||||
|
||||
@@ -88,7 +88,7 @@ enum class E: Base { v1, v2, ..., vN };
|
||||
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
|
||||
```
|
||||
|
||||
## <boost/describe/enumerators.hpp>
|
||||
## <boost/describe/{zwsp}enumerators{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -332,7 +332,7 @@ Since the library does not provide a way to describe bases and members separatel
|
||||
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
|
||||
are provided separately for consistency.
|
||||
|
||||
## <boost/describe/enum_to_string.hpp>
|
||||
## <boost/describe/{zwsp}enum_to_string{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -349,7 +349,7 @@ The function `enum_to_string` returns the name of the enumerator `e`. `E` must
|
||||
be a described enumeration type. If `e` does not correspond to one of the described
|
||||
values, the function returns `def`.
|
||||
|
||||
## <boost/describe/enum_from_string.hpp>
|
||||
## <boost/describe/{zwsp}enum_from_string{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -440,7 +440,7 @@ Returns the negated result of `operator<`.
|
||||
Outputs a representation of `t` to `os` by recursively using `operator<<`
|
||||
to output all bases and then all members.
|
||||
|
||||
## <boost/describe/descriptor_by_name.hpp>
|
||||
## <boost/describe/{zwsp}descriptor_by_name{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -478,7 +478,7 @@ using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
|
||||
using D = descriptor_by_name<L, N>; // descriptor for SomeType::some_member
|
||||
```
|
||||
|
||||
## <boost/describe/descriptor_by_pointer.hpp>
|
||||
## <boost/describe/{zwsp}descriptor_by_pointer{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace app
|
||||
{
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
bool operator==( T const& t1, T const& t2 )
|
||||
{
|
||||
bool r = true;
|
||||
|
||||
101
example/fmtlib_class_formatter.cpp
Normal file
101
example/fmtlib_class_formatter.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <boost/mp11.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<class T> struct fmt::formatter<T, char, std::enable_if_t<
|
||||
boost::describe::has_describe_bases<T>::value &&
|
||||
boost::describe::has_describe_members<T>::value &&
|
||||
!std::is_union<T>::value>>
|
||||
{
|
||||
constexpr auto parse( format_parse_context& ctx )
|
||||
{
|
||||
auto it = ctx.begin(), end = ctx.end();
|
||||
|
||||
if( it != end && *it != '}' )
|
||||
{
|
||||
ctx.error_handler().on_error( "invalid format" );
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
auto format( T const& t, format_context& ctx ) const
|
||||
{
|
||||
using namespace boost::describe;
|
||||
|
||||
using Bd = describe_bases<T, mod_any_access>;
|
||||
using Md = describe_members<T, mod_any_access>;
|
||||
|
||||
auto out = ctx.out();
|
||||
|
||||
*out++ = '{';
|
||||
|
||||
bool first = true;
|
||||
|
||||
boost::mp11::mp_for_each<Bd>([&](auto D){
|
||||
|
||||
if( !first )
|
||||
{
|
||||
*out++ = ',';
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
||||
out = fmt::format_to( out, " {}",
|
||||
(typename decltype(D)::type const&)t );
|
||||
});
|
||||
|
||||
boost::mp11::mp_for_each<Md>([&](auto D){
|
||||
|
||||
if( !first )
|
||||
{
|
||||
*out++ = ',';
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
||||
out = fmt::format_to( out, " .{}={}",
|
||||
D.name, t.*D.pointer );
|
||||
});
|
||||
|
||||
if( !first )
|
||||
{
|
||||
*out++ = ' ';
|
||||
}
|
||||
|
||||
*out++ = '}';
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
struct point
|
||||
{
|
||||
int x, y;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT( point, (), (x, y) )
|
||||
|
||||
struct color
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT( color, (), (r, g, b) )
|
||||
|
||||
struct line: color
|
||||
{
|
||||
point first, last;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT( line, (color), (first, last) )
|
||||
|
||||
int main()
|
||||
{
|
||||
fmt::print( "{}\n", line{ { 255, 192, 16 }, { 1, 2 }, { 3, 4 } } );
|
||||
}
|
||||
60
example/fmtlib_enum_formatter.cpp
Normal file
60
example/fmtlib_enum_formatter.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<class T> struct fmt::formatter<T, char, std::enable_if_t<
|
||||
boost::describe::has_describe_enumerators<T>::value>>
|
||||
{
|
||||
private:
|
||||
|
||||
using U = std::underlying_type_t<T>;
|
||||
|
||||
fmt::formatter<fmt::string_view, char> sf_;
|
||||
fmt::formatter<U, char> nf_;
|
||||
|
||||
public:
|
||||
|
||||
constexpr auto parse( format_parse_context& ctx )
|
||||
{
|
||||
auto i1 = sf_.parse( ctx );
|
||||
auto i2 = nf_.parse( ctx );
|
||||
|
||||
if( i1 != i2 )
|
||||
{
|
||||
ctx.error_handler().on_error( "invalid format" );
|
||||
}
|
||||
|
||||
return i1;
|
||||
}
|
||||
|
||||
auto format( T const& t, format_context& ctx ) const
|
||||
{
|
||||
char const * s = boost::describe::enum_to_string( t, 0 );
|
||||
|
||||
if( s )
|
||||
{
|
||||
return sf_.format( s, ctx );
|
||||
}
|
||||
else
|
||||
{
|
||||
return nf_.format( static_cast<U>( t ), ctx );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum E1
|
||||
{
|
||||
v1, v2, v3 = 11
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_ENUM( E1, v1, v2, v3 )
|
||||
|
||||
int main()
|
||||
{
|
||||
fmt::print( "{:_^10}\n", E1::v1 );
|
||||
fmt::print( "{:_^10}\n", (E1)7 );
|
||||
}
|
||||
@@ -19,7 +19,7 @@ template<class T,
|
||||
class D1 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
|
||||
|
||||
T tag_invoke( boost::json::value_to_tag<T> const&, boost::json::value const& v )
|
||||
{
|
||||
|
||||
@@ -15,7 +15,8 @@ namespace app
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
std::size_t hash_value( T const & t )
|
||||
{
|
||||
std::size_t r = 0;
|
||||
|
||||
125
example/pm_to_string.cpp
Normal file
125
example/pm_to_string.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 12
|
||||
# pragma GCC diagnostic ignored "-Wrestrict" // false positive
|
||||
#endif
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <boost/mp11.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr auto equals( T1 t1, T2 t2, int ) -> decltype( t1 == t2 )
|
||||
{
|
||||
return t1 == t2;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool equals( T1 /*t1*/, T2 /*t2*/, long )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace boost::describe;
|
||||
|
||||
template<class T, class C,
|
||||
class L = describe_members<C, mod_any_access | mod_any_member>>
|
||||
char const* get_member_name( T C::* pm, int )
|
||||
{
|
||||
char const * name = nullptr;
|
||||
|
||||
boost::mp11::mp_for_each<L>([&](auto D){
|
||||
|
||||
if( equals( D.pointer, pm, 0 ) ) name = D.name;
|
||||
|
||||
});
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
template<class T, class C>
|
||||
char const* get_member_name( T C::* /*pm*/, long )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T, class C>
|
||||
std::string pm_to_string( T C::* pm )
|
||||
{
|
||||
char const * name = ::detail::get_member_name( pm, 0 );
|
||||
|
||||
if( name == nullptr ) name = "(unknown)";
|
||||
|
||||
return "&" + boost::core::type_name<C>() + "::" + name
|
||||
+ " [" + boost::core::type_name<T>() + "]";
|
||||
}
|
||||
|
||||
template<class T, class C>
|
||||
std::ostream& operator<<( std::ostream& os, T C::* pm )
|
||||
{
|
||||
os << pm_to_string( pm );
|
||||
return os;
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
int m;
|
||||
int f() const { return m; }
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (m, f))
|
||||
|
||||
struct Y: public X
|
||||
{
|
||||
int m;
|
||||
int g() const { return -m; }
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y, (X), (m, g))
|
||||
|
||||
struct Z
|
||||
{
|
||||
void h() {}
|
||||
};
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
|
||||
// MSVC doesn't support BOOST_DESCRIBE_CLASS inside
|
||||
// templates until 2022 in C++20 mode
|
||||
|
||||
template<class T1, class T2> struct pair
|
||||
{
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
BOOST_DESCRIBE_CLASS(pair, (), (first, second), (), ())
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << &X::m << std::endl;
|
||||
std::cout << &X::f << std::endl;
|
||||
|
||||
std::cout << &Y::m << std::endl;
|
||||
std::cout << &Y::f << std::endl;
|
||||
std::cout << &Y::g << std::endl;
|
||||
|
||||
std::cout << &Z::h << std::endl;
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
std::cout << &pair<int, float>::second << std::endl;
|
||||
#endif
|
||||
}
|
||||
@@ -10,7 +10,8 @@ using namespace boost::describe;
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
std::ostream& operator<<( std::ostream & os, T const & t )
|
||||
{
|
||||
os << "{";
|
||||
|
||||
@@ -24,8 +24,8 @@ template<class Archive, class T,
|
||||
class D3 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D4 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<
|
||||
boost::mp11::mp_empty<D2>::value && boost::mp11::mp_empty<D4>::value> >
|
||||
class En = std::enable_if_t< boost::mp11::mp_empty<D2>::value &&
|
||||
boost::mp11::mp_empty<D4>::value && !std::is_union<T>::value> >
|
||||
|
||||
void serialize( Archive & ar, T & t, boost::serialization::version_type )
|
||||
{
|
||||
|
||||
57
example/struct_to_tuple.cpp
Normal file
57
example/struct_to_tuple.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <tuple>
|
||||
|
||||
namespace desc = boost::describe;
|
||||
|
||||
template<class T, template<class...> class L, class... D>
|
||||
auto struct_to_tuple_impl( T const& t, L<D...> )
|
||||
{
|
||||
return std::make_tuple( t.*D::pointer... );
|
||||
}
|
||||
|
||||
template<class T,
|
||||
class Dm = desc::describe_members<T,
|
||||
desc::mod_public | desc::mod_inherited>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
auto struct_to_tuple( T const& t )
|
||||
{
|
||||
return struct_to_tuple_impl( t, Dm() );
|
||||
}
|
||||
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct X
|
||||
{
|
||||
int a = 1;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (a))
|
||||
|
||||
struct Y
|
||||
{
|
||||
float b = 3.14f;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y, (), (b))
|
||||
|
||||
struct Z: X, Y
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Z, (X, Y), ())
|
||||
|
||||
int main()
|
||||
{
|
||||
Z z;
|
||||
|
||||
auto tp = struct_to_tuple( z );
|
||||
|
||||
std::cout <<
|
||||
boost::core::type_name<decltype(tp)>() << ": "
|
||||
<< std::get<0>(tp) << ", " << std::get<1>(tp);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ template<class T,
|
||||
class D1 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
|
||||
|
||||
void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, T const & t )
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace describe
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> using _describe_bases = decltype( boost_base_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_bases = decltype( boost_base_descriptor_fn( static_cast<T**>(0) ) );
|
||||
|
||||
template<unsigned M> struct base_filter
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace describe
|
||||
friend BOOST_DESCRIBE_PRIVATE_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
|
||||
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
|
||||
static_assert(std::is_class<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_BASES(C, BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_PUBLIC_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_PROTECTED_MEMBERS(C) \
|
||||
@@ -54,17 +54,17 @@ namespace describe
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS_(...) BOOST_DESCRIBE_PRIVATE_MEMBERS(__VA_ARGS__)
|
||||
|
||||
#define BOOST_DESCRIBE_CLASS(C, Bases, Public, Protected, Private) \
|
||||
friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
|
||||
friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
|
||||
friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
|
||||
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
|
||||
static_assert(std::is_class<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
|
||||
BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
|
||||
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,12 +37,12 @@ template<class... T> auto base_descriptor_fn_impl( int, T... )
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,4 +27,12 @@
|
||||
# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST const
|
||||
#endif
|
||||
|
||||
#define BOOST_DESCRIBE_MAYBE_UNUSED
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(maybe_unused)
|
||||
# undef BOOST_DESCRIBE_MAYBE_UNUSED
|
||||
# define BOOST_DESCRIBE_MAYBE_UNUSED [[maybe_unused]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED
|
||||
|
||||
@@ -53,24 +53,24 @@ template<class C, class F> constexpr auto mfn( F * p ) { return p; }
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
|
||||
}
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
inline auto boost_enum_descriptor_fn( E* ) \
|
||||
inline auto boost_enum_descriptor_fn( E** ) \
|
||||
{ return boost::describe::detail::enum_descriptor_fn_impl( 0
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM_ENTRY(E, e) , []{ struct _boost_desc { \
|
||||
@@ -56,6 +56,7 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM(E, ...) \
|
||||
namespace should_use_BOOST_DESCRIBE_NESTED_ENUM {} \
|
||||
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_ENUM should only be used with enums"); \
|
||||
BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, __VA_ARGS__) \
|
||||
@@ -70,14 +71,15 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
|
||||
#else
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM(E, ...) \
|
||||
namespace should_use_BOOST_DESCRIBE_NESTED_ENUM {} \
|
||||
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_ENUM should only be used with enums"); \
|
||||
BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
|
||||
BOOST_DESCRIBE_ENUM_END(E)
|
||||
|
||||
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) \
|
||||
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_NESTED_ENUM should only be used with enums"); \
|
||||
friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
|
||||
BOOST_DESCRIBE_ENUM_END(E)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace describe
|
||||
|
||||
// describe_enumerators<E>
|
||||
|
||||
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E*>(0) ) );
|
||||
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E**>(0) ) );
|
||||
|
||||
// has_describe_enumerators<E>
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace detail
|
||||
|
||||
// _describe_members<T>
|
||||
|
||||
template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
|
||||
template<class T> using _describe_members = mp11::mp_append<_describe_public_members<T>, _describe_protected_members<T>, _describe_private_members<T>>;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ BOOST_DESCRIBE_ENUM(modifiers,
|
||||
mod_function,
|
||||
mod_any_member,
|
||||
mod_inherited,
|
||||
mod_hidden);
|
||||
mod_hidden)
|
||||
|
||||
BOOST_DESCRIBE_CONSTEXPR_OR_CONST modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace detail
|
||||
{
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Bd = describe::describe_bases<T, mod_any_access>,
|
||||
class Md = describe::describe_members<T, mod_any_access>>
|
||||
bool eq( T const& t1, T const& t2 )
|
||||
{
|
||||
bool r = true;
|
||||
@@ -48,8 +48,8 @@ bool eq( T const& t1, T const& t2 )
|
||||
}
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Bd = describe::describe_bases<T, mod_any_access>,
|
||||
class Md = describe::describe_members<T, mod_any_access>>
|
||||
bool lt( T const& t1, T const& t2 )
|
||||
{
|
||||
int r = 0;
|
||||
@@ -73,8 +73,8 @@ bool lt( T const& t1, T const& t2 )
|
||||
}
|
||||
|
||||
template<class Os, class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Bd = describe::describe_bases<T, mod_any_access>,
|
||||
class Md = describe::describe_members<T, mod_any_access>>
|
||||
void print( Os& os, T const& t )
|
||||
{
|
||||
os << "{";
|
||||
@@ -109,49 +109,49 @@ namespace operators
|
||||
{
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator==( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::eq( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator!=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::eq( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator<( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::lt( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator>=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::lt( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator>( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::lt( t2, t1 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator<=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::lt( t2, t1 );
|
||||
}
|
||||
|
||||
template<class T, class Ch, class Tr> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value,
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
|
||||
std::basic_ostream<Ch, Tr>&>
|
||||
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"description": "A C++14 reflection library.",
|
||||
"category": [
|
||||
"Emulation",
|
||||
"Metaprogramming"
|
||||
]
|
||||
}
|
||||
|
||||
11
test/Jamfile
11
test/Jamfile
@@ -48,6 +48,9 @@ compile test_d_type.cpp ;
|
||||
compile-fail enum_struct_fail.cpp ;
|
||||
compile-fail struct_enum_fail.cpp ;
|
||||
|
||||
compile-fail enum_nested_fail.cpp ;
|
||||
compile-fail nested_enum_fail.cpp ;
|
||||
|
||||
run class_template_test.cpp ;
|
||||
|
||||
run has_enumerators_test.cpp ;
|
||||
@@ -63,6 +66,12 @@ run operator_lt_test.cpp ;
|
||||
run descriptor_by_name_test.cpp ;
|
||||
run descriptor_by_pointer_test.cpp ;
|
||||
|
||||
compile unnamed_namespace_test.cpp ;
|
||||
compile unnamed_namespace_test2.cpp ;
|
||||
|
||||
run union_test.cpp ;
|
||||
run union_test2.cpp ;
|
||||
|
||||
# examples
|
||||
|
||||
obj describe_cxx14 : describe_cxx14.cpp ;
|
||||
@@ -85,3 +94,5 @@ run ../example/json_rpc.cpp : : : $(CXX14) $(JSON) ;
|
||||
run ../example/hash_value.cpp : : : $(CXX14) ;
|
||||
run ../example/equality.cpp : : : $(CXX14) ;
|
||||
link ../example/console.cpp : $(CXX14) $(JSON) ;
|
||||
run ../example/struct_to_tuple.cpp : : : $(CXX14) ;
|
||||
run ../example/pm_to_string.cpp : : : $(CXX14) ;
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
# pragma warning(disable: 4510) // default constructor could not be generated
|
||||
# pragma warning(disable: 4610) // struct can never be instantiated
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
17
test/cmake_install_test/CMakeLists.txt
Normal file
17
test/cmake_install_test/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2018, 2019, 2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_install_test LANGUAGES CXX)
|
||||
|
||||
find_package(boost_describe REQUIRED)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main Boost::describe)
|
||||
|
||||
enable_testing()
|
||||
add_test(main main)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
||||
49
test/cmake_install_test/main.cpp
Normal file
49
test/cmake_install_test/main.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2017, 2020, 2021, 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#define BOOST_TEST(expr) assert(expr)
|
||||
#define BOOST_TEST_EQ(x1, x2) assert((x1)==(x2))
|
||||
|
||||
struct X
|
||||
{
|
||||
int m;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (m))
|
||||
|
||||
struct Y: public X
|
||||
{
|
||||
void m() {}
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y, (X), (m))
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#pragma message "Skipping test because C++14 is not available"
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BOOST_DEFINE_ENUM(E, v1, v2, v3)
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe;
|
||||
using namespace boost::mp11;
|
||||
|
||||
BOOST_TEST_EQ( (mp_size< describe_enumerators<E> >::value), 3 );
|
||||
BOOST_TEST_EQ( (mp_size< describe_bases<Y, mod_any_access> >::value), 1 );
|
||||
BOOST_TEST_EQ( (mp_size< describe_members<Y, mod_any_access | mod_inherited | mod_hidden> >::value), 1 );
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
23
test/cmake_subdir_test/CMakeLists.txt
Normal file
23
test/cmake_subdir_test/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright 2018-2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(../.. boostorg/describe)
|
||||
add_subdirectory(../../../assert boostorg/assert)
|
||||
add_subdirectory(../../../config boostorg/config)
|
||||
add_subdirectory(../../../core boostorg/core)
|
||||
add_subdirectory(../../../mp11 boostorg/mp11)
|
||||
add_subdirectory(../../../static_assert boostorg/static_assert)
|
||||
add_subdirectory(../../../throw_exception boostorg/throw_exception)
|
||||
|
||||
add_executable(quick ../quick.cpp)
|
||||
target_link_libraries(quick Boost::describe Boost::core)
|
||||
|
||||
enable_testing()
|
||||
add_test(quick quick)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --no-tests=error -C $<CONFIG>)
|
||||
@@ -21,7 +21,7 @@ BOOST_DESCRIBE_ENUM(E1, v101, v102)
|
||||
enum class E2 { v201 = 201, v202 = 202 };
|
||||
BOOST_DESCRIBE_ENUM(E2, v201, v202)
|
||||
|
||||
BOOST_DEFINE_ENUM(E3, v301, v302);
|
||||
BOOST_DEFINE_ENUM(E3, v301, v302)
|
||||
BOOST_DEFINE_ENUM_CLASS(E4, v401, v402)
|
||||
|
||||
int main()
|
||||
|
||||
18
test/enum_nested_fail.cpp
Normal file
18
test/enum_nested_fail.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/enum.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#error "Skipping test because C++14 is not available"
|
||||
|
||||
#else
|
||||
|
||||
struct S1 {
|
||||
enum E1 {};
|
||||
BOOST_DESCRIBE_ENUM(E1)
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
@@ -21,7 +21,7 @@ BOOST_DESCRIBE_ENUM(E1, v1)
|
||||
enum class E2 { v2 };
|
||||
BOOST_DESCRIBE_ENUM(E2, v2)
|
||||
|
||||
BOOST_DEFINE_ENUM(E3, v3);
|
||||
BOOST_DEFINE_ENUM(E3, v3)
|
||||
BOOST_DEFINE_ENUM_CLASS(E4, v4)
|
||||
|
||||
int main()
|
||||
|
||||
@@ -11,9 +11,9 @@ enum E1
|
||||
v1_1 = 5
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E1, v1_1);
|
||||
BOOST_DESCRIBE_ENUM(E1, v1_1)
|
||||
|
||||
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3);
|
||||
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3)
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX11)
|
||||
|
||||
@@ -30,12 +30,12 @@ enum class E2
|
||||
v2_2 = 7
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E2, v2_1, v2_2);
|
||||
BOOST_DESCRIBE_ENUM(E2, v2_1, v2_2)
|
||||
|
||||
BOOST_DEFINE_FIXED_ENUM(E4, int, v4_1, v4_2, v4_3, v4_4);
|
||||
BOOST_DEFINE_FIXED_ENUM(E4, int, v4_1, v4_2, v4_3, v4_4)
|
||||
|
||||
BOOST_DEFINE_ENUM_CLASS(E5, v5_1, v5_2, v5_3, v5_4, v5_5);
|
||||
BOOST_DEFINE_FIXED_ENUM_CLASS(E6, int, v6_1, v6_2, v6_3, v6_4, v6_5, v6_6);
|
||||
BOOST_DEFINE_ENUM_CLASS(E5, v5_1, v5_2, v5_3, v5_4, v5_5)
|
||||
BOOST_DEFINE_FIXED_ENUM_CLASS(E6, int, v6_1, v6_2, v6_3, v6_4, v6_5, v6_6)
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ struct X3 {};
|
||||
class X4 {};
|
||||
union X5 {};
|
||||
|
||||
struct X6: X1 {};
|
||||
struct X7: X2 {};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::describe::has_describe_bases;
|
||||
@@ -46,6 +49,8 @@ int main()
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X3>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X4>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X5>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X6>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X7>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<void>));
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ BOOST_DESCRIBE_ENUM(E1, v1)
|
||||
enum class E2 { v2 };
|
||||
BOOST_DESCRIBE_ENUM(E2, v2)
|
||||
|
||||
BOOST_DEFINE_ENUM(E3, v3);
|
||||
BOOST_DEFINE_ENUM(E3, v3)
|
||||
BOOST_DEFINE_ENUM_CLASS(E4, v4)
|
||||
|
||||
enum E5 { v5 };
|
||||
|
||||
@@ -27,6 +27,9 @@ struct X3 {};
|
||||
class X4 {};
|
||||
union X5 {};
|
||||
|
||||
struct X6: X1 {};
|
||||
struct X7: X2 {};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::describe::has_describe_members;
|
||||
@@ -46,6 +49,8 @@ int main()
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X3>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X4>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X5>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X6>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X7>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<void>));
|
||||
|
||||
|
||||
16
test/nested_enum_fail.cpp
Normal file
16
test/nested_enum_fail.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/enum.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#error "Skipping test because C++14 is not available"
|
||||
|
||||
#else
|
||||
|
||||
enum E1 {};
|
||||
BOOST_DESCRIBE_NESTED_ENUM(E1);
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
@@ -20,9 +20,11 @@ namespace app
|
||||
|
||||
struct X
|
||||
{
|
||||
void f() const {}
|
||||
static void g() {}
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), ())
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (f, g))
|
||||
|
||||
using boost::describe::operators::operator==;
|
||||
using boost::describe::operators::operator<<;
|
||||
|
||||
@@ -20,9 +20,11 @@ namespace app
|
||||
|
||||
struct X
|
||||
{
|
||||
void f() const {}
|
||||
static void g() {}
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), ())
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (f, g))
|
||||
|
||||
using boost::describe::operators::operator<=;
|
||||
using boost::describe::operators::operator>=;
|
||||
|
||||
79
test/union_test.cpp
Normal file
79
test/union_test.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2020, 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/members.hpp>
|
||||
#include <boost/describe/class.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX11)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
|
||||
int main() {}
|
||||
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
union A
|
||||
{
|
||||
int m1;
|
||||
static int m2;
|
||||
int f1() const { return m1; }
|
||||
static int f2() { return m2; }
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(A, (), (m1, m2, f1, f2))
|
||||
|
||||
int A::m2;
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe;
|
||||
using namespace boost::mp11;
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_any_access | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m1 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_public );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m2 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f1 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f2 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX11)
|
||||
153
test/union_test2.cpp
Normal file
153
test/union_test2.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright 2020, 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/members.hpp>
|
||||
#include <boost/describe/class.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX11)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
|
||||
int main() {}
|
||||
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
union A
|
||||
{
|
||||
public:
|
||||
|
||||
int m1;
|
||||
static int m2;
|
||||
int f1() const { return m1; }
|
||||
static int f2() { return m2; }
|
||||
|
||||
protected:
|
||||
|
||||
int m3;
|
||||
static int m4;
|
||||
int f3() const { return m3; }
|
||||
static int f4() { return m4; }
|
||||
|
||||
private:
|
||||
|
||||
int m5;
|
||||
static int m6;
|
||||
int f5() const { return m5; }
|
||||
static int f6() { return m6; }
|
||||
|
||||
BOOST_DESCRIBE_CLASS(A, (), (m1, m2, f1, f2), (m3, m4, f3, f4), (m5, m6, f5, f6))
|
||||
|
||||
friend int main();
|
||||
};
|
||||
|
||||
int A::m2;
|
||||
int A::m4;
|
||||
int A::m6;
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe;
|
||||
using namespace boost::mp11;
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_public | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m1 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_public );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m2 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f1 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f2 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_protected | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m3 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m3" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_protected );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m4 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m4" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_protected | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f3 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f3" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_protected | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f4 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f4" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_protected | mod_static | mod_function );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_private | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m5 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m5" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_private );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m6 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m6" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_private | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f5 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f5" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_private | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f6 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f6" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_private | mod_static | mod_function );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX11)
|
||||
35
test/unnamed_namespace_test.cpp
Normal file
35
test/unnamed_namespace_test.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum E { v };
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E, v)
|
||||
|
||||
struct S
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(S, (), ())
|
||||
|
||||
class C
|
||||
{
|
||||
BOOST_DESCRIBE_CLASS(C, (), (), (), ())
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
45
test/unnamed_namespace_test2.cpp
Normal file
45
test/unnamed_namespace_test2.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum E { v };
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E, v)
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), ())
|
||||
|
||||
class Y
|
||||
{
|
||||
BOOST_DESCRIBE_CLASS(Y, (), (), (), ())
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace boost::describe;
|
||||
|
||||
using L1 = describe_enumerators<E>;
|
||||
|
||||
using L2 = describe_bases<X, mod_any_access>;
|
||||
using L3 = describe_members<X, mod_any_access>;
|
||||
|
||||
using L4 = describe_bases<Y, mod_any_access>;
|
||||
using L5 = describe_members<Y, mod_any_access>;
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
Reference in New Issue
Block a user