Compare commits

...

77 Commits

Author SHA1 Message Date
Peter Dimov
fc458d48c7 Change internal functions to take T** instead of T* to prevent derived to base conversions (closes #22) 2021-12-11 19:28:16 +02:00
Peter Dimov
6cc4ddafd7 Test non-described classes derived from described ones (refs #22) 2021-12-11 19:14:19 +02:00
Peter Dimov
ed1175b33a Merge branch 'maybe-unused' of https://github.com/ecatmur/describe into feature/pr-24 2021-11-17 02:22:16 +02:00
Peter Dimov
d4ebe0943e Add test for enums and classes in unnamed namespaces (refs #23) 2021-11-17 02:20:22 +02:00
Ed Catmur
1fa144623d Sprinkle [[maybe_unused]] on descriptors
Suppresses Wunused-function / Wunneeded-internal-declaration (clang) on internal-linkage types

https://github.com/boostorg/describe/issues/23
2021-11-16 21:35:33 +00:00
Peter Dimov
5032f55ac1 Update categories in libraries.json 2021-11-08 00:34:30 +02:00
Peter Dimov
71bfb07be2 Add example/struct_to_tuple.cpp 2021-10-28 01:28:07 +03:00
Peter Dimov
fc15f03c34 Add {zwsp} to long header names 2021-10-27 06:51:54 +03:00
Peter Dimov
2fc0e817ad Document descriptor_by_pointer 2021-10-27 06:24:09 +03:00
Peter Dimov
84fe8aa21e Add descriptor_by_pointer 2021-10-27 06:09:54 +03:00
Peter Dimov
003b2bdc50 Document descriptor_by_name 2021-10-27 05:42:38 +03:00
Peter Dimov
8437f2e62e Fix msvc-14.0 2021-10-27 04:31:35 +03:00
Peter Dimov
448174f346 Add descriptor_by_name 2021-10-27 04:13:29 +03:00
Peter Dimov
2935bca3b1 Update README, implementation section 2021-10-26 18:46:12 +03:00
Peter Dimov
e407d4da19 Document operators 2021-10-26 17:39:59 +03:00
Peter Dimov
2accb05ce5 Reset os.width in operator<< 2021-10-26 17:32:21 +03:00
Peter Dimov
128e3667d6 Add operators.hpp 2021-10-26 07:09:30 +03:00
Peter Dimov
8cf28d7b6e Include enum_from_string.hpp in describe.hpp 2021-10-26 06:21:56 +03:00
Peter Dimov
7397e8d66a Document enum_from_string 2021-10-26 05:40:26 +03:00
Peter Dimov
c3f16f3332 Add enum_from_string.hpp 2021-10-26 05:33:14 +03:00
Peter Dimov
890c1afcda Bump workaround in class_template_test.cpp 2021-10-26 04:18:37 +03:00
Peter Dimov
caa4cb6bf0 Bump workarounds in members_test7.cpp 2021-10-26 04:17:26 +03:00
Peter Dimov
ffa4790292 Add msvc-14.3 to ci.yml 2021-10-26 04:15:50 +03:00
Peter Dimov
f7d2f12cd4 Document enum_to_string 2021-10-26 04:13:18 +03:00
Peter Dimov
53d577428e Make enum_to_string noexcept 2021-10-26 04:12:58 +03:00
Peter Dimov
9c351a463f Add enum_to_string.hpp 2021-10-25 20:22:14 +03:00
Peter Dimov
af01484087 Document has_* 2021-10-25 20:08:13 +03:00
Peter Dimov
d5e79ee67d Remove superfluous semicolons 2021-10-25 19:53:53 +03:00
Peter Dimov
300ea0bebe Add has_describe_members 2021-10-25 18:45:26 +03:00
Peter Dimov
5a4c425f32 Add has_describe_bases 2021-10-25 18:40:38 +03:00
Peter Dimov
fe23aeeee4 Update ci.yml 2021-10-25 18:01:19 +03:00
Peter Dimov
daaec68db6 Update ci.yml 2021-10-25 17:40:36 +03:00
Peter Dimov
b6c41956ec Add has_describe_enumerators 2021-10-25 17:36:58 +03:00
Peter Dimov
7e6f861f89 Document mod_any_member 2021-06-16 22:39:45 +03:00
Peter Dimov
4a4dd302cb Add mod_any_member 2021-06-16 22:33:02 +03:00
Peter Dimov
be5bf613e6 Add test/CMakeLists.txt 2021-06-16 05:39:59 +03:00
Peter Dimov
57e62f34b8 Avoid g++ error 2021-06-16 05:19:57 +03:00
Peter Dimov
7e9f1f0eb9 Add class_template_test 2021-06-16 04:57:14 +03:00
Peter Dimov
0b65ca3229 Update ci.yml 2021-06-08 20:30:43 +03:00
Peter Dimov
f66002254b Add CMakeLists.txt 2021-05-28 00:14:09 +03:00
Peter Dimov
abbc5bec0c Fix example to compile on VS2015 2021-05-03 08:52:17 +03:00
Peter Dimov
ef93d95e71 Fix capitalization, MSVC warning 2021-05-03 05:38:05 +03:00
Peter Dimov
c48ef40b1d Add example/console.cpp 2021-05-03 04:53:07 +03:00
Peter Dimov
78c861d0bc Add example/equality.cpp 2021-05-03 04:05:03 +03:00
Peter Dimov
23cc0011ad Remove doc/html 2021-05-03 03:53:34 +03:00
Peter Dimov
245c2de80a Add example/hash_value.cpp 2021-05-03 03:52:36 +03:00
Peter Dimov
22eaa99867 Update GHA 2021-04-26 01:31:39 +03:00
Peter Dimov
53d7313731 Update README 2021-04-26 00:05:32 +03:00
Peter Dimov
65066cd2d0 Update documentation 2021-03-20 21:53:41 +02:00
Peter Dimov
94a80a6812 Add BOOST_DESCRIBE_NESTED_ENUM 2021-03-20 02:28:22 +02:00
Peter Dimov
62c032ff22 Add static_asserts in BOOST_DESCRIBE_ENUM and BOOST_DESCRIBE_STRUCT (fixes #8) 2021-03-17 16:42:58 +02:00
Peter Dimov
bef1e45cb0 Add compile-fail tests for describing enums as structs and vice versa (refs #8) 2021-03-17 16:29:37 +02:00
Peter Dimov
92afba2c39 Disable MS warning 5104 (ntverp.h under new pp) for JSON examples 2021-03-17 15:08:42 +02:00
Peter Dimov
031c55b392 Update GHA handling of cxxflags 2021-03-17 14:43:37 +02:00
Peter Dimov
36c52dcbd6 Add -Zc:preprocessor configurations to GHA and Appveyor 2021-03-17 14:29:54 +02:00
Peter Dimov
4ca49a6af2 Remove noexcept from functions to avoid g++-7 warning and enable C++03 compilation 2021-03-16 06:34:12 +02:00
Peter Dimov
1bf6dddac0 Add a test for overloaded functions returning std::pair 2021-03-16 06:20:20 +02:00
Peter Dimov
39cf63cee1 Update documentation 2021-03-16 05:08:03 +02:00
Peter Dimov
5ebca2615a Merge branch 'develop' into feature/overloaded 2021-03-16 01:52:02 +02:00
Peter Dimov
7f36a2c798 Add a protected base to members_test5.cpp 2021-03-16 01:51:47 +02:00
Peter Dimov
564f849629 Use PP_NAME, PP_POINTER when describing members; add overloaded_test 2021-03-16 01:44:53 +02:00
Peter Dimov
ed26d4c495 Add BOOST_DESCRIBE_PP_NAME, BOOST_DESCRIBE_PP_POINTER 2021-03-16 01:21:20 +02:00
Peter Dimov
8aa347b171 Update supported compilers 2021-03-15 17:19:02 +02:00
Peter Dimov
acf14803ba Enable syntax highlighting 2021-03-14 20:39:36 +02:00
Peter Dimov
ffb6787d28 Add -std g++ 5/6/7 configurations to Travis 2021-03-14 07:34:09 +02:00
Peter Dimov
e15c09c848 Reenable BOOST_DESCRIBE_CXX14 for -std=c++14 on g++ 5, 6, 7 2021-03-14 06:49:02 +02:00
Peter Dimov
c9f780cbfb Allow trailing comma in enum descriptions and definitions 2021-03-14 06:47:14 +02:00
Peter Dimov
ae5c3c862f Add detail/pp_utilities.hpp 2021-03-14 06:30:01 +02:00
Peter Dimov
c6fa6f125e Fix handling of empty enums 2021-03-14 01:30:59 +02:00
Peter Dimov
e503b32c51 Add empty_enum_test 2021-03-14 01:24:33 +02:00
Peter Dimov
ee415d4001 Rename internal classes from D to _boost_desc 2021-03-14 01:14:58 +02:00
Peter Dimov
b1e0566668 Add a test using various entities named D 2021-03-14 01:11:03 +02:00
Peter Dimov
f251e6f320 Add a boost prefix to descriptor functions 2021-03-14 01:00:45 +02:00
Peter Dimov
70eadd17a7 Update enumerators_test.cpp to use the macros even when C++14 is not available 2021-03-14 00:53:26 +02:00
Peter Dimov
02cdf8734f Update documentation 2021-03-14 00:46:24 +02:00
Peter Dimov
6f8e4c879b Remove BOOST_DESCRIBE_ENUM_CLASS; use BOOST_DESCRIBE_ENUM_BEGIN, BOOST_DESCRIBE_ENUM_ENTRY, BOOST_DESCRIBE_ENUM_END 2021-03-14 00:44:25 +02:00
Peter Dimov
f76971d52c Update documentation 2021-03-14 00:30:05 +02:00
72 changed files with 3338 additions and 2184 deletions

View File

@@ -19,18 +19,15 @@ jobs:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-16.04
os: ubuntu-18.04
install: g++-4.8
- toolset: gcc-4.9
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.9
- toolset: gcc-5
cxxstd: "03,11,14,14-gnu,1z,1z-gnu"
os: ubuntu-16.04
os: ubuntu-18.04
install: g++-5
- toolset: gcc-6
cxxstd: "03,11,14,14-gnu,1z,1z-gnu"
os: ubuntu-16.04
os: ubuntu-18.04
install: g++-6
- toolset: gcc-7
cxxstd: "03,11,14,14-gnu,17,17-gnu"
@@ -38,51 +35,38 @@ jobs:
- toolset: gcc-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
install: g++-8
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
os: ubuntu-20.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
- toolset: clang
compiler: clang++-3.5
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.5
- toolset: clang
compiler: clang++-3.6
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.6
- toolset: clang
compiler: clang++-3.7
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.7
- toolset: clang
compiler: clang++-3.8
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.8
os: ubuntu-20.04
install: g++-10
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-11
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
@@ -90,16 +74,29 @@ jobs:
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "03,11,14,17,2a"
cxxstd: "03,11,14,17"
os: ubuntu-20.04
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-12
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
@@ -159,6 +156,20 @@ jobs:
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64
cxxflags: "-Zc:preprocessor"
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: msvc-14.3
cxxstd: "14,17,latest"
addrmd: 32,64
cxxflags: "-Zc:preprocessor"
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
@@ -195,4 +206,5 @@ jobs:
shell: cmd
run: |
cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
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

View File

@@ -22,7 +22,7 @@ matrix:
include:
- os: linux
compiler: g++-5
env: TOOLSET=gcc CXXSTD=14-gnu,1z-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,1z,1z-gnu
addons:
apt:
packages:
@@ -32,7 +32,7 @@ matrix:
- os: linux
compiler: g++-6
env: TOOLSET=gcc CXXSTD=14-gnu,1z-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,1z,1z-gnu
addons:
apt:
packages:
@@ -42,7 +42,7 @@ matrix:
- os: linux
compiler: g++-7
env: TOOLSET=gcc CXXSTD=14-gnu,17-gnu
env: TOOLSET=gcc CXXSTD=14,14-gnu,17,17-gnu
addons:
apt:
packages:

25
CMakeLists.txt Normal file
View File

@@ -0,0 +1,25 @@
# Generated by `boostdep --cmake describe`
# 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_describe VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
add_library(boost_describe INTERFACE)
add_library(Boost::describe ALIAS boost_describe)
target_include_directories(boost_describe INTERFACE include)
target_link_libraries(boost_describe
INTERFACE
Boost::mp11
)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

View File

@@ -2,19 +2,19 @@
A C++14 reflection library. Provides macros for describing enumerators and
struct/class members, and primitives for querying this information. See
[the documentation](https://pdimov.github.io/describe) for more information
and usage examples.
[the documentation](https://www.boost.org/doc/libs/develop/libs/describe/)
for more information and usage examples.
## Supported Compilers
* GCC 5 or later with `-std=gnu++14` or above
* GCC 8 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* 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
Tested on [Travis](https://travis-ci.org/github/pdimov/describe/) and
Tested on [Github Actions](https://github.com/boostorg/describe/actions) and
[Appveyor](https://ci.appveyor.com/project/pdimov/describe).
## License
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
Distributed under the
[Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).

View File

@@ -31,6 +31,11 @@ environment:
- 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
@@ -49,4 +54,5 @@ build: off
test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/describe/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
- if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS%
- b2 -j3 libs/describe/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker

1
doc/.gitignore vendored
View File

@@ -1 +1,2 @@
/pdf/
/html/

View File

@@ -9,11 +9,15 @@ Peter Dimov
:toc: left
:toclevels: 4
:idprefix:
:listing-caption: Code Example
:docinfo: private-footer
:source-highlighter: rouge
:source-language: c++
:leveloffset: +1
include::describe/overview.adoc[]
include::describe/changes.adoc[]
include::describe/enums.adoc[]
include::describe/classes.adoc[]
include::describe/examples.adoc[]

16
doc/describe/changes.adoc Normal file
View 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
////
[#changes]
# Revision History
:idprefix:
## 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`.

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -8,6 +8,8 @@ https://www.boost.org/LICENSE_1_0.txt
# Describing Class Types
:idprefix: classes_
## Class Types with Public Members
If you have a `struct`
```
@@ -31,8 +33,15 @@ It takes three arguments: the `struct` name, a list of base classes
(empty in our example), and a list of (public) members by name (this includes
both data members and member functions.)
To describe a class type with protected or private members, use the
`BOOST_DESCRIBE_CLASS` macro instead, placing it _inside the class_.
Since `BOOST_DESCRIBE_STRUCT` is placed outside the type, it's non-intrisive,
does not require access to the definition, and can therefore be used to describe
third-party types or types defined in system headers.
## Class Types with Protected or Private Members
To describe a class type, use the `BOOST_DESCRIBE_CLASS` macro instead, placing
it _inside the class_. This gives the macro access to the protected and private
members, but is intrusive and requires access to the definition.
```
class Y: private X
@@ -61,6 +70,8 @@ private:
It takes three member lists, for the public, protected, and private members.
## Retrieving Class Properties
Once a type `T` is annotated, its properties can be retrieved via
`describe_bases<T, M>` and `describe_members<T, M>` (`M` is a bitmask of
modifiers such as `mod_public | mod_static | mod_function`).
@@ -73,17 +84,11 @@ These primitives are defined in namespace `boost::describe`, in the headers
presence of `mod_public` includes the public bases in the result, its absence
excludes them. The other two modifiers work similarly.
(At least in principle. The current implementation cannot distinguish between
protected and private base classes, so protected bases are returned as private.
Consequently, using `mod_protected` gives no result. Lifting this limitation
would require compiler support.)
`describe_members` takes a bitwise-or combination of the following possible
modifiers: `mod_public`, `mod_protected`, `mod_private`, `mod_static`,
`mod_function`, `mod_inherited`, `mod_hidden`.
`mod_function`, `mod_any_member`, `mod_inherited`, `mod_hidden`.
The access modifiers work the same as with `describe_bases` (except here
`mod_protected` actually works when `BOOST_DESCRIBE_CLASS` is used.)
The access modifiers work the same as with `describe_bases`.
(For types annotated with `BOOST_DESCRIBE_STRUCT`, the protected and private
member lists will be empty.)
@@ -94,6 +99,9 @@ the nonstatic members are returned.
When `mod_function` is present, the member functions are returned, otherwise
the data members are returned.
When `mod_any_member` is present, `mod_static` and `mod_function` are ignored
and all members are returned regardless of kind.
When `mod_inherited` is present, members of base classes are also returned.
When `mod_hidden` is present, hidden inherited members are included. A member
@@ -127,3 +135,55 @@ For an example of how to use the base and data member descriptors, see
For an example of how to use member function descriptors, see
<<example_json_rpc>>.
## Overloaded Member Functions
To describe an overloaded member function, you will need to resort to
a more complicated syntax, as simply listing its name (say, `f`) will make
the library attempt to form a member pointer with `&X::f`, which would fail
because it's not clear to which `f` this expression refers.
To disambiguate, precede the function name with the type of the function, in
parentheses, as shown in the following example:
```
struct X
{
int f();
int f() const;
void f( int x );
};
BOOST_DESCRIBE_STRUCT(X, (), (
(int ()) f,
(int () const) f,
(void (int)) f
))
```
The type of the function is the same as its declaration, without the name.
Be sure to retain the space between the parenthesized function type and its name,
because omitting it will compile happily on GCC and Clang but will lead to
inscrutable errors on MSVC due to its nonstandard preprocessor.
Pay attention to the proper placement of the parentheses, because a mistake there
will also lead to hard to decipher compiler errors, on all compilers.
The same technique also works with `BOOST_DESCRIBE_CLASS`, and with static member
functions:
```
class Y
{
public:
static void f( int x );
static void f( int x, int y );
BOOST_DESCRIBE_CLASS(Y, (), ((void (int)) f, (void (int, int)) f), (), ())
};
```
The case where a member function and a static member function have the same name
and the same function type is currently not supported.

View File

@@ -8,5 +8,5 @@ https://www.boost.org/LICENSE_1_0.txt
# Copyright and License
:idprefix:
This documentation is copyright 2020 Peter Dimov and is distributed under
This documentation is copyright 2020, 2021 Peter Dimov and is distributed under
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].

View File

@@ -28,8 +28,6 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, v3)
The macro is defined in `<boost/describe/enum.hpp>` and should be placed in
the same namespace as the enum.
For scoped enums, use `BOOST_DESCRIBE_ENUM_CLASS` instead.
If your enumerators don't have initializers, instead of repeating them
```
@@ -49,6 +47,28 @@ For defining `enum class E2` instead, use `BOOST_DEFINE_ENUM_CLASS`. To add
an underlying type, i.e. `enum E3: int` or `enum class E4: unsigned char`,
use `BOOST_DEFINE_FIXED_ENUM` and `BOOST_DEFINE_FIXED_ENUM_CLASS`, respectively.
If your enumeration type is nested inside a class or a `struct`, use the
`BOOST_DESCRIBE_NESTED_ENUM` macro next to the `enum`, as follows:
```
class X
{
private:
enum class E
{
v1,
v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
// ...
};
```
Once an enumeration type `E` is annotated, one can use `describe_enumerators<E>`
to obtain a _descriptor list_. (`describe_enumerators` is defined in the
`boost::describe` namespace, in `<boost/describe/enumerators.hpp>`.)

View File

@@ -35,37 +35,36 @@ include::../../example/printing_enums_rt.cpp[lines=5..-1]
## enum_to_string
This example shows a function that, given an enumerator
value, returns its name.
Providing `enum_to_string` in a library is made difficult
by the fact that the desired behavior when the passed value
does not correspond to a named enumerator varies depending
on the specific use case. But, since defining the function
is trivial when `describe_enumerators` is available, every
user can easily have his own.
This specific example elects to return `"(unnamed)"` when
the enum value doesn't have a name.
value, returns its name. If the value does not correspond
to a named value, the function returns `"(unnamed)"`.
[source]
----
include::../../example/enum_to_string.cpp[lines=5..-1]
----
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
value doesn't correspond to a named enumerator.
[#example_string_to_enum]
## string_to_enum
The opposite of the previous example; returns an enumerator
value when given the enumerator name. The same problem exists
here with respect to the error handling strategy when the string
passed does not correspond to any enumerator name. This example
throws an exception.
value when given the enumerator name. When the string passed
does not correspond to any enumerator name, throws an exception.
[source]
----
include::../../example/string_to_enum.cpp[lines=5..-1]
----
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
enumerator value is assigned to the output argument.
[#example_print_function]
## Defining a Universal Print Function
@@ -86,12 +85,100 @@ change its state and hence cannot violate its invariant.)
include::../../example/print_function.cpp[lines=5..-1]
----
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
containing the described application types, like in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
using boost::describe::operators::operator<<;
}
```
[#example_hash_value]
## Implementing hash_value
This example defines a universal `hash_value` overload that
computes the hash value of an annotated struct or class. It
does so by iterating over the described bases and members and
calling `boost::hash_combine` on each.
The overload is defined in namespace `app` in order to apply
to all annotated classes also defined in `app`.
[source]
----
include::../../example/hash_value.cpp[lines=5..-1]
----
[#example_equality]
## Implementing operator==
This example defines a universal `operator==` overload that
iterates over the described bases and members and compares
them for equality using `==`.
The overload is defined in namespace `app` in order to apply
to all annotated classes also defined in `app`.
[source]
----
include::../../example/equality.cpp[lines=5..-1]
----
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
containing the described application types, like in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
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]
----
[#example_to_json]
## Automatic Conversion to JSON
This example defines a universal `tag_invoke` overload that
automatically converts an annotated struct to a
http://master.json.cpp.al[Boost.JSON] value by iterating
http://boost.org/libs/json[Boost.JSON] value by iterating
over the described public members and adding them to the return
`boost::json::object`.
@@ -136,7 +223,7 @@ include::../../example/serialization.cpp[lines=5..-1]
This example defines a generic `call` function that can be used to
invoke a member function by name, with the arguments passed in a
http://master.json.cpp.al[Boost.JSON] array. The result is returned
http://boost.org/libs/json[Boost.JSON] array. The result is returned
in a `boost::json::value`.
[source]
@@ -144,3 +231,14 @@ in a `boost::json::value`.
include::../../example/json_rpc.cpp[lines=5..-1]
----
[#example_console]
## Interactive Variable Console
This example implements an interactive console that allows printing
and modifying variables. It uses http://boost.org/libs/json[Boost.JSON]
for converting the variables to and from a string form.
[source]
----
include::../../example/console.cpp[lines=9..-1]
----

View File

@@ -14,22 +14,24 @@ https://boost.org/libs/mp11[Boost.Mp11].
## Supported Compilers
* GCC 5 or later with `-std=gnu++14` or above
* GCC 8 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* 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
Tested on https://travis-ci.org/github/pdimov/describe[Travis] and
https://ci.appveyor.com/project/pdimov/describe[Appveyor].
Tested on https://github.com/boostorg/describe/actions[Github Actions]
and https://ci.appveyor.com/project/pdimov/describe[Appveyor].
## Limitations
This implementation has the following limitations:
* Up to 52 elements are supported in the lists of enumerators,
bases, and members.
* Protected base classes cannot be distinguished from private
base classes and are considered private.
* Overloaded member functions are not supported. Member names
must be unique within the class.
* Bitfields are not supported.
base classes when the described class is final, and are considered
private.
* Bitfields are not supported. It's not possible to form a pointer
to member to a bitfield.
* Reference members are not supported. It's not possible to form a
pointer to member to a reference.
* Anonymous unions are not supported.
* Reference members are not supported.

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -12,7 +12,8 @@ https://www.boost.org/LICENSE_1_0.txt
```
#define BOOST_DESCRIBE_ENUM(E, ...) /*...*/
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...) /*...*/
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) /*...*/
#define BOOST_DEFINE_ENUM(E, ...) \
enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
@@ -48,11 +49,12 @@ struct Di
```
where `vi` is the corresponding identifier passed to the macro.
### BOOST_DESCRIBE_ENUM_CLASS
### BOOST_DESCRIBE_NESTED_ENUM
`BOOST_DESCRIBE_ENUM_CLASS(E, v1, ..., vN)` should be used instead of
`BOOST_DESCRIBE_ENUM` when `E` is a scoped enumeration type, and has
the same effect.
`BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2, ..., vN)` is similar to
`BOOST_DESCRIBE_ENUM` and is used to annotate enumeration types nested inside
class (or `struct`) types. It should be placed in the class type where the
`enum` is defined.
### BOOST_DEFINE_ENUM
@@ -67,7 +69,7 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
`BOOST_DEFINE_ENUM_CLASS(E, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM_CLASS(E, v1, v2, ..., vN)
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```
### BOOST_DEFINE_FIXED_ENUM
@@ -83,10 +85,10 @@ BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
`BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E: Base { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM_CLASS(E, v1, v2, ..., vN)
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```
## <boost/describe/enumerators.hpp>
## <boost/describe/{zwsp}enumerators{zwsp}.hpp>
```
namespace boost {
@@ -94,6 +96,8 @@ namespace describe {
template<class E> using describe_enumerators = /*...*/;
template<class E> using has_describe_enumerators = /*...*/;
} }
```
@@ -114,6 +118,14 @@ struct Di
```
where `vi` is the i-th enumerator.
If `E` is not a described enumeration type, `describe_enumerators<E>` causes
a substitution failure.
### has_describe_enumerators<E>
`has_describe_enumerators<E>::value` is `true` when `E` is a described
enumeration type, `false` otherwise.
## <boost/describe/class.hpp>
```
@@ -196,8 +208,9 @@ enum modifiers
mod_virtual = 8,
mod_static = 16,
mod_function = 32,
mod_inherited = 64,
mod_hidden = 128,
mod_any_member = 64,
mod_inherited = 128,
mod_hidden = 256,
};
constexpr modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );
@@ -217,6 +230,7 @@ following flags:
* `mod_virtual` - returned when a base class is a virtual base
* `mod_static` - returns static members (when not given, returns nonstatic members)
* `mod_function` - returns member functions (when not given, returns data members)
* `mod_any_member` - overrides `mod_static` and `mod_function` and returns all members regardless of kind
* `mod_inherited` - includes members of base classes
* `mod_hidden` - includes hidden inherited members
@@ -228,6 +242,8 @@ namespace describe {
template<class T, unsigned M> using describe_bases = /*...*/;
template<class T> using has_describe_bases = /*...*/;
} }
```
@@ -253,6 +269,18 @@ where `type` is the type of the base class, and `modifiers` are a bitwise-or
combination of `mod_public`, `mod_protected`, `mod_private`, and `mod_virtual`
that reflects the properties of the base class.
If `T` is not a described class type, `describe_bases<T, M>` causes a
substitution failure.
### has_describe_bases<T>
`has_describe_bases<T>::value` is `true` when `T` is a described class type,
`false` otherwise.
Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.
## <boost/describe/members.hpp>
```
@@ -261,14 +289,16 @@ namespace describe {
template<class T, unsigned M> using describe_members = /*...*/;
template<class T> using has_describe_members = /*...*/;
} }
```
### describe_members<T, M>
`M` must be a bitwise-or combination of `mod_public`, `mod_protected`,
`mod_private`, `mod_static`, `mod_function`, `mod_inherited`, and
`mod_hidden`, and acts as a filter.
`mod_private`, `mod_static`, `mod_function`, `mod_any_member`,
`mod_inherited`, and `mod_hidden`, and acts as a filter.
`describe_members<T, M>` returns `L<D1, D2, ..., Dn>`, where `L` is a class
template of the form
@@ -290,6 +320,189 @@ member, and `modifiers` are a bitwise-or combination of `mod_public`,
`mod_protected`, `mod_private`, `mod_static`, `mod_function`, `mod_inherited`,
and `mod_hidden` that reflects the properties of the member.
If `T` is not a described class type, `describe_members<T, M>` causes a
substitution failure.
### has_describe_members<T>
`has_describe_members<T>::value` is `true` when `T` is a described class type,
`false` otherwise.
Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.
## <boost/describe/{zwsp}enum_to_string{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class E> char const * enum_to_string( E e, char const * def ) noexcept;
} }
```
### enum_to_string
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/{zwsp}enum_from_string{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class E> bool enum_from_string( char const * name, E & e ) noexcept;
} }
```
### enum_from_string
The function `enum_from_string` assigns to `e` the enumerator value corresponding
to `name` and returns `true`. `E` must be a described enumeration type. If `name`
does not correspond to one of the described values, the function returns `false`.
## <boost/describe/operators.hpp>
```
namespace boost {
namespace describe {
namespace operators {
template<class T> bool operator==( T const& t1, T const& t2 );
template<class T> bool operator!=( T const& t1, T const& t2 );
template<class T> bool operator<( T const& t1, T const& t2 );
template<class T> bool operator>( T const& t1, T const& t2 );
template<class T> bool operator<=( T const& t1, T const& t2 );
template<class T> bool operator>=( T const& t1, T const& t2 );
template<class T, class Ch, class Tr>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t );
} } }
```
The header `<boost/describe/operators.hpp>` defines generic operators for
described class types. They are used by bringing them into the namespace
containing the described types via a using declaration, as in the example
below:
```
namespace app
{
struct X
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
}
```
### operator==
If all bases and members compare equal, returns `true`, otherwise `false`.
### operator!=
Returns the negation of `operator==`.
### operator<
Performs a lexicographical comparison over the bases and members in sequence
using `operator<` and returns the result.
### operator>
Returns the result of `operator<` with the arguments reversed.
### operator\<=
Returns the negated result of `operator>`.
### operator>=
Returns the negated result of `operator<`.
### operator<<
Outputs a representation of `t` to `os` by recursively using `operator<<`
to output all bases and then all members.
## <boost/describe/{zwsp}descriptor_by_name{zwsp}.hpp>
```
namespace boost {
namespace describe {
#define BOOST_DESCRIBE_MAKE_NAME(s) /*...*/
template<class L, class N> using descriptor_by_name = /*...*/;
} }
```
### BOOST_DESCRIBE_MAKE_NAME
The macro `BOOST_DESCRIBE_MAKE_NAME` creates a type that identifies the
name given as an argument. It should be used as follows:
```
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
```
### descriptor_by_name
`descriptor_by_name<L, N>` searches the descriptor list `L` for the member
with the name identified by `N`. `N` should be a type created by
`BOOST_DESCRIBE_MAKE_NAME` as in the above example. `L` is intended to be
a list returned by `describe_members`, although since enumerator descriptors
also have `::name`, a list returned by `describe_enumerators` will work as
well.
.Using descriptor_by_name
```
using L = describe_members<SomeType, mod_any_access>;
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
using D = descriptor_by_name<L, N>; // descriptor for SomeType::some_member
```
## <boost/describe/{zwsp}descriptor_by_pointer{zwsp}.hpp>
```
namespace boost {
namespace describe {
template<class L, auto Pm> using descriptor_by_pointer = /*...*/;
} }
```
### descriptor_by_pointer
`descriptor_by_pointer<L, Pm>` searches the descriptor list `L` for the member
pointer `Pm`. `L` should be a list returned by `describe_members`.
Since `auto` template parameters are a {cpp}17 feature, using
`descriptor_by_pointer` requires {cpp}17.
.Using descriptor_by_pointer
```
using L = describe_members<X, mod_any_access>;
using D = descriptor_by_pointer<L, &X::a>; // descriptor for X::a
```
## <boost/describe.hpp>
This convenience header includes all the headers previously

File diff suppressed because it is too large Load Diff

129
example/console.cpp Normal file
View File

@@ -0,0 +1,129 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning(disable: 4702) // unreachable code
#endif
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/utility/string_view.hpp>
#include <string>
#include <stdexcept>
#include <vector>
#include <map>
#include <iostream>
// get variable
template<class Scope> boost::json::value get( Scope& scope, boost::string_view name )
{
using Md = boost::describe::describe_members<Scope, boost::describe::mod_public>;
bool found = false;
boost::json::value result;
boost::mp11::mp_for_each<Md>([&](auto D) {
if( !found && name == D.name )
{
result = boost::json::value_from( scope.*D.pointer );
found = true;
}
});
if( !found )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': no such variable" );
}
return result;
}
// set variable
template<class T> void set_impl( T & t, boost::string_view /*name*/, boost::json::value const& value )
{
t = boost::json::value_to<T>( value );
}
template<class T> void set_impl( T const & /*t*/, boost::string_view name, boost::json::value const& /*value*/ )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': variable cannot be modified" );
}
template<class Scope> void set( Scope& scope, boost::string_view name, boost::json::value const& value )
{
using Md = boost::describe::describe_members<Scope, boost::describe::mod_public>;
bool found = false;
boost::mp11::mp_for_each<Md>([&](auto D) {
if( !found && name == D.name )
{
set_impl( scope.*D.pointer, name, value );
found = true;
}
});
if( !found )
{
throw std::invalid_argument(
std::string( "'" ) + std::string( name ) + "': no such variable" );
}
}
//
struct globals
{
std::string const 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.";
int x = 1;
double y = 3.14;
std::vector<int> v{ 1, 2, 3 };
std::map<std::string, double> m{ { "BTC", 44898.68 }, { "ETH", 1386.57 } };
};
BOOST_DESCRIBE_STRUCT( globals, (), (help, x, y, v, m) )
int main()
{
globals g_;
for( ;; )
{
std::cout << "\n> ";
std::string line;
std::getline( std::cin, line );
try
{
std::size_t i = line.find( '=' );
if( i != std::string::npos )
{
set( g_, line.substr( 0, i ), boost::json::parse( line.substr( i + 1 ) ) );
}
else
{
std::cout << get( g_, line ) << std::endl;
}
}
catch( std::exception const& x )
{
std::cout << "Error: " << x.what() << std::endl;
}
}
}

73
example/equality.cpp Normal file
View File

@@ -0,0 +1,73 @@
// 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 <boost/mp11.hpp>
#include <boost/variant2/variant.hpp>
#include <vector>
using namespace boost::describe;
namespace app
{
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
bool operator==( T const& t1, T const& t2 )
{
bool r = true;
boost::mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
r = r && (B const&)t1 == (B const&)t2;
});
boost::mp11::mp_for_each<Md>([&](auto D){
r = r && t1.*D.pointer == t2.*D.pointer;
});
return r;
}
struct A
{
int x = 1;
};
BOOST_DESCRIBE_STRUCT(A, (), (x))
struct B
{
int y = 2;
};
BOOST_DESCRIBE_STRUCT(B, (), (y))
struct C
{
std::vector<boost::variant2::variant<A, B>> v;
};
BOOST_DESCRIBE_STRUCT(C, (), (v))
} // namespace app
#include <iostream>
int main()
{
app::C c1, c2, c3;
c1.v.push_back( app::A{} );
c2.v.push_back( app::A{} );
c3.v.push_back( app::B{} );
std::cout << std::boolalpha
<< ( c1 == c2 ) << ' '
<< ( c1 == c3 ) << std::endl;
}

72
example/hash_value.cpp Normal file
View File

@@ -0,0 +1,72 @@
// 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 <boost/mp11.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/variant2/variant.hpp>
#include <vector>
using namespace boost::describe;
namespace app
{
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
std::size_t hash_value( T const & t )
{
std::size_t r = 0;
boost::mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
boost::hash_combine( r, (B const&)t );
});
boost::mp11::mp_for_each<Md>([&](auto D){
boost::hash_combine( r, t.*D.pointer );
});
return r;
}
struct A
{
int x = 1;
};
BOOST_DESCRIBE_STRUCT(A, (), (x))
struct B
{
int y = 2;
};
BOOST_DESCRIBE_STRUCT(B, (), (y))
struct C
{
std::vector<boost::variant2::variant<A, B>> v;
};
BOOST_DESCRIBE_STRUCT(C, (), (v))
} // namespace app
#include <iostream>
int main()
{
app::C c;
c.v.push_back( app::A{} );
c.v.push_back( app::B{} );
std::cout << boost::hash<app::C>()( c ) << std::endl;
}

View File

@@ -12,7 +12,8 @@
[[noreturn]] void throw_invalid_name( char const * name, char const * type )
{
throw std::runtime_error(
std::string( "Invalid enumerator name '" ) + name + "' for enum type '" + type + "'" );
std::string( "Invalid enumerator name '" ) + name
+ "' for enum type '" + type + "'" );
}
template<class E> E string_to_enum( char const * name )

View File

@@ -0,0 +1,55 @@
// 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>>
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);
}

View File

@@ -11,5 +11,10 @@
#include <boost/describe/enum.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/modifiers.hpp>
#include <boost/describe/enum_to_string.hpp>
#include <boost/describe/enum_from_string.hpp>
#include <boost/describe/operators.hpp>
#include <boost/describe/descriptor_by_name.hpp>
#include <boost/describe/descriptor_by_pointer.hpp>
#endif // #ifndef BOOST_DESCRIBE_HPP_INCLUDED

View File

@@ -1,16 +1,18 @@
#ifndef BOOST_DESCRIBE_BASES_HPP_INCLUDED
#define BOOST_DESCRIBE_BASES_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// 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/modifiers.hpp>
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
#include <boost/mp11/algorithm.hpp>
#include <type_traits>
namespace boost
{
@@ -19,17 +21,27 @@ namespace describe
namespace detail
{
template<class T> using _describe_bases = decltype( _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
{
template<class T> using fn = mp11::mp_bool< ( M & mod_any_access & T::modifiers ) != 0 >;
};
template<class T, class En = void> struct has_describe_bases: std::false_type
{
};
template<class T> struct has_describe_bases<T, void_t<_describe_bases<T>>>: std::true_type
{
};
} // namespace detail
template<class T, unsigned M> using describe_bases = mp11::mp_copy_if_q<detail::_describe_bases<T>, detail::base_filter<M>>;
template<class T> using has_describe_bases = detail::has_describe_bases<T>;
} // namespace describe
} // namespace boost

View File

@@ -16,6 +16,7 @@
#include <boost/describe/detail/bases.hpp>
#include <boost/describe/detail/members.hpp>
#include <type_traits>
namespace boost
{
@@ -33,6 +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"); \
BOOST_DESCRIBE_BASES(C, BOOST_DESCRIBE_PP_UNPACK Bases) \
BOOST_DESCRIBE_PUBLIC_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Members) \
BOOST_DESCRIBE_PROTECTED_MEMBERS(C) \
@@ -52,16 +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) \
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, "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

View File

@@ -0,0 +1,41 @@
#ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED
#define BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/cx_streq.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integral.hpp>
namespace boost
{
namespace describe
{
namespace detail
{
template<class D, class N> using match_by_name = mp11::mp_bool<cx_streq(N::name(), D::name)>;
#define BOOST_DESCRIBE_MAKE_NAME_IMPL2(s, k) struct _boost_name_##s##_##k { static constexpr char const * name() { return #s; } }
#define BOOST_DESCRIBE_MAKE_NAME_IMPL(s, k) BOOST_DESCRIBE_MAKE_NAME_IMPL2(s, k)
} // namespace detail
#define BOOST_DESCRIBE_MAKE_NAME(s) BOOST_DESCRIBE_MAKE_NAME_IMPL(s, __LINE__)
template<class L, class N> using descriptor_by_name = mp11::mp_at<L, mp11::mp_find_if_q<L, mp11::mp_bind_back<detail::match_by_name, N>>>;
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_NAME_HPP_INCLUDED

View File

@@ -0,0 +1,48 @@
#ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED
#define BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integral.hpp>
namespace boost
{
namespace describe
{
namespace detail
{
template<class Pm> constexpr bool cx_pmeq( Pm p1, Pm p2 )
{
return p1 == p2;
}
template<class Pm1, class Pm2> constexpr bool cx_pmeq( Pm1, Pm2 )
{
return false;
}
template<auto Pm> struct match_by_pointer
{
template<class D> using fn = mp11::mp_bool< cx_pmeq( D::pointer, Pm ) >;
};
} // namespace detail
template<class L, auto Pm> using descriptor_by_pointer = mp11::mp_at<L, mp11::mp_find_if_q<L, detail::match_by_pointer<Pm>>>;
} // namespace describe
} // namespace boost
#endif // __cpp_nontype_template_parameter_auto
#endif // #ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED

View File

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

View File

@@ -21,15 +21,18 @@
#endif
#if defined(BOOST_DESCRIBE_CXX14) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 5 && __GNUC__ <= 7 && defined(__STRICT_ANSI__)
// g++ 5..7 with -std=c++14 doesn't support the variadic extension we need, use -std=gnu++14
# undef BOOST_DESCRIBE_CXX14
#endif
#if defined(BOOST_DESCRIBE_CXX11)
# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST constexpr
#else
# 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

View File

@@ -0,0 +1,30 @@
#ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
namespace boost
{
namespace describe
{
namespace detail
{
constexpr bool cx_streq( char const * s1, char const * s2 )
{
return s1[0] == s2[0] && ( s1[0] == 0 || cx_streq( s1 + 1, s2 + 1 ) );
}
} // namespace detail
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX11)
#endif // #ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED

View File

@@ -7,6 +7,7 @@
#include <boost/describe/modifiers.hpp>
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
@@ -43,30 +44,33 @@ template<unsigned M, class... T> auto member_descriptor_fn_impl( int, T... )
return list<member_descriptor<T, M>...>();
}
#define BOOST_DESCRIBE_MEMBER_IMPL(C, m) , []{ struct D { \
static constexpr auto pointer() noexcept { return &C::m; } \
static constexpr auto name() noexcept { return #m; } }; return D(); }()
template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
template<class C, class F> constexpr auto mfn( F * p ) { return p; }
#define BOOST_DESCRIBE_MEMBER_IMPL(C, m) , []{ struct _boost_desc { \
static constexpr auto pointer() noexcept { return BOOST_DESCRIBE_PP_POINTER(C, m); } \
static constexpr auto name() noexcept { return BOOST_DESCRIBE_PP_NAME(m); } }; return _boost_desc(); }()
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto _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 _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 _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 _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 _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 _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

View File

@@ -5,66 +5,66 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_DESCRIBE_PP_EXPAND(x) x
#include <boost/describe/detail/pp_utilities.hpp>
#define BOOST_DESCRIBE_PP_FOR_EACH_0(F, a)
#define BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, x) F(a, x)
#define BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_52(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(F(a, x) BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, x) BOOST_DESCRIBE_PP_CALL(F, a, x)
#define BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_1(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_2(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_3(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_4(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_5(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_6(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_7(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_8(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_9(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_10(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_11(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_12(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_13(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_14(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_15(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_16(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_17(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_18(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_19(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_20(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_21(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_22(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_23(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_24(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_25(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_26(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_27(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_28(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_29(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_30(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_31(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_32(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_33(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_34(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_35(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_36(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_37(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_38(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_39(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_40(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_41(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_42(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_43(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_44(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_45(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_46(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_47(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_48(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_49(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_50(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_FOR_EACH_52(F, a, x, ...) BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_FOR_EACH_51(F, a, __VA_ARGS__))
#define BOOST_DESCRIBE_PP_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, V, ...) V
#define BOOST_DESCRIBE_PP_FE_EXTRACT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, V, ...) V
#define BOOST_DESCRIBE_PP_FOR_EACH(F, ...) \
BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXTRACT(__VA_ARGS__, \
BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_EXPAND(BOOST_DESCRIBE_PP_FE_EXTRACT(__VA_ARGS__, \
BOOST_DESCRIBE_PP_FOR_EACH_52, \
BOOST_DESCRIBE_PP_FOR_EACH_51, \
BOOST_DESCRIBE_PP_FOR_EACH_50, \

View File

@@ -0,0 +1,92 @@
#ifndef BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_DESCRIBE_PP_EXPAND(x) x
#define BOOST_DESCRIBE_PP_CAT(x, y) BOOST_DESCRIBE_PP_CAT_I(x, y)
#define BOOST_DESCRIBE_PP_CAT_I(x, ...) x ## __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_FIRST(x) BOOST_DESCRIBE_PP_FIRST_I((x))
#define BOOST_DESCRIBE_PP_FIRST_I(x) BOOST_DESCRIBE_PP_FIRST_II x
#define BOOST_DESCRIBE_PP_FIRST_II(x, ...) x
#else
#define BOOST_DESCRIBE_PP_FIRST(x) BOOST_DESCRIBE_PP_FIRST_I(x)
#define BOOST_DESCRIBE_PP_FIRST_I(x, ...) x
#endif
#define BOOST_DESCRIBE_PP_IS_PAREN_I(x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_IS_PAREN_I_, BOOST_DESCRIBE_PP_IS_PAREN_II x)
#define BOOST_DESCRIBE_PP_IS_PAREN_II(...) 0
#define BOOST_DESCRIBE_PP_IS_PAREN_I_0 1,
#define BOOST_DESCRIBE_PP_IS_PAREN_I_BOOST_DESCRIBE_PP_IS_PAREN_II 0,
#define BOOST_DESCRIBE_PP_IS_PAREN(x) BOOST_DESCRIBE_PP_FIRST(BOOST_DESCRIBE_PP_IS_PAREN_I(x))
#define BOOST_DESCRIBE_PP_EMPTY
#define BOOST_DESCRIBE_PP_IS_EMPTY(x) BOOST_DESCRIBE_PP_IS_EMPTY_I(BOOST_DESCRIBE_PP_IS_PAREN(x), BOOST_DESCRIBE_PP_IS_PAREN(x BOOST_DESCRIBE_PP_EMPTY ()))
#define BOOST_DESCRIBE_PP_IS_EMPTY_I(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_II(x, y)
#define BOOST_DESCRIBE_PP_IS_EMPTY_II(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_III(x, y)
#define BOOST_DESCRIBE_PP_IS_EMPTY_III(x, y) BOOST_DESCRIBE_PP_IS_EMPTY_III_ ## x ## y
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_00 0
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_01 1
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_10 0
#define BOOST_DESCRIBE_PP_IS_EMPTY_III_11 0
#define BOOST_DESCRIBE_PP_CALL(F, a, x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_CALL_I_, BOOST_DESCRIBE_PP_IS_EMPTY(x))(F, a, x)
#define BOOST_DESCRIBE_PP_CALL_I_0(F, a, x) F(a, x)
#define BOOST_DESCRIBE_PP_CALL_I_1(F, a, x)
#define BOOST_DESCRIBE_PP_PARSE(x) BOOST_DESCRIBE_PP_CAT(BOOST_DESCRIBE_PP_PARSE_I_, BOOST_DESCRIBE_PP_PARSE_II x)
#define BOOST_DESCRIBE_PP_PARSE_II(...) 0, (__VA_ARGS__),
#define BOOST_DESCRIBE_PP_PARSE_I_BOOST_DESCRIBE_PP_PARSE_II 0, ~,
#define BOOST_DESCRIBE_PP_PARSE_I_0 1
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_NAME(x) BOOST_DESCRIBE_PP_NAME_I(BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_NAME_I(x) BOOST_DESCRIBE_PP_NAME_II((x))
#define BOOST_DESCRIBE_PP_NAME_II(x) BOOST_DESCRIBE_PP_NAME_III x
#define BOOST_DESCRIBE_PP_NAME_III(x, y, z) #z
#else
#define BOOST_DESCRIBE_PP_NAME(x) BOOST_DESCRIBE_PP_NAME_I(BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_NAME_I(x) BOOST_DESCRIBE_PP_NAME_II(x)
#define BOOST_DESCRIBE_PP_NAME_II(x, y, z) #z
#endif
// template<class C, class F> constexpr auto mfn( F C::* p ) { return p; }
// template<class C, class F> constexpr auto mfn( F * p ) { return p; }
#define BOOST_DESCRIBE_PP_POINTER(C, x) BOOST_DESCRIBE_PP_POINTER_I(C, BOOST_DESCRIBE_PP_PARSE(x))
#define BOOST_DESCRIBE_PP_EXPAND_V(...) __VA_ARGS__
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_PP_POINTER_I(C, x) BOOST_DESCRIBE_PP_POINTER_II((C, x))
#define BOOST_DESCRIBE_PP_POINTER_II(x) BOOST_DESCRIBE_PP_POINTER_III x
#define BOOST_DESCRIBE_PP_POINTER_III(C, x, y, z) BOOST_DESCRIBE_PP_POINTER_III_##x(C, y, z)
#define BOOST_DESCRIBE_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_DESCRIBE_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_DESCRIBE_PP_EXPAND_V y>(&C::z)
#else
#define BOOST_DESCRIBE_PP_POINTER_I(C, x) BOOST_DESCRIBE_PP_POINTER_II(C, x)
#define BOOST_DESCRIBE_PP_POINTER_II(C, x, y, z) BOOST_DESCRIBE_PP_POINTER_III_##x(C, y, z)
#define BOOST_DESCRIBE_PP_POINTER_III_0(C, y, z) &C::z
#define BOOST_DESCRIBE_PP_POINTER_III_1(C, y, z) ::boost::describe::detail::mfn<C, BOOST_DESCRIBE_PP_EXPAND_V y>(&C::z)
#endif
#endif // #ifndef BOOST_DESCRIBE_DETAIL_PP_UTILITIES_HPP_INCLUDED

View File

@@ -0,0 +1,32 @@
#ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
namespace boost
{
namespace describe
{
namespace detail
{
template<class...> struct make_void
{
using type = void;
};
template<class... T> using void_t = typename make_void<T...>::type;
} // namespace detail
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX11)
#endif // #ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED

View File

@@ -5,17 +5,19 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <boost/describe/detail/config.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#define BOOST_DESCRIBE_ENUM(E, ...)
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...)
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...)
#else
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
namespace boost
{
namespace describe
@@ -39,31 +41,69 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
return list<enum_descriptor<T>...>();
}
#define BOOST_DESCRIBE_ENUM_IMPL(E, e) , []{ struct D { \
static constexpr auto value() noexcept { return e; } \
static constexpr auto name() noexcept { return #e; } }; return D(); }()
#define BOOST_DESCRIBE_ENUM_BEGIN(E) \
inline auto boost_enum_descriptor_fn( E** ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0
#define BOOST_DESCRIBE_ENUM_CLASS_IMPL(E, e) , []{ struct D { \
#define BOOST_DESCRIBE_ENUM_ENTRY(E, e) , []{ struct _boost_desc { \
static constexpr auto value() noexcept { return E::e; } \
static constexpr auto name() noexcept { return #e; } }; return D(); }()
static constexpr auto name() noexcept { return #e; } }; return _boost_desc(); }()
#define BOOST_DESCRIBE_ENUM_END(E) ); }
} // namespace detail
#define BOOST_DESCRIBE_ENUM(E, ...) inline auto _enum_descriptor_fn( E* ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_IMPL, E, __VA_ARGS__) ); }
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DESCRIBE_ENUM_CLASS(E, ...) inline auto _enum_descriptor_fn( E* ) \
{ return boost::describe::detail::enum_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_CLASS_IMPL, E, __VA_ARGS__) ); }
#define BOOST_DESCRIBE_ENUM(E, ...) \
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__) \
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_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, __VA_ARGS__) \
BOOST_DESCRIBE_ENUM_END(E)
#else
#define BOOST_DESCRIBE_ENUM(E, ...) \
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_ENUM should only be used with enums"); \
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"); \
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)
#endif
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#if defined(_MSC_VER) && !defined(__clang__)
#define BOOST_DEFINE_ENUM(E, ...) enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM(E, Base, ...) enum E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)
#else
#define BOOST_DEFINE_ENUM(E, ...) enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_ENUM_CLASS(E, ...) enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM(E, Base, ...) enum E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, ##__VA_ARGS__)
#endif
#endif // #ifndef BOOST_DESCRIBE_ENUM_HPP_INCLUDED

View File

@@ -0,0 +1,44 @@
#ifndef BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED
// 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/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/enumerators.hpp>
#include <boost/mp11/algorithm.hpp>
#include <cstring>
namespace boost
{
namespace describe
{
template<class E, class De = describe_enumerators<E>>
bool enum_from_string( char const* name, E& e ) noexcept
{
bool found = false;
mp11::mp_for_each<De>([&](auto D){
if( !found && std::strcmp( D.name, name ) == 0 )
{
found = true;
e = D.value;
}
});
return found;
}
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_ENUM_FROM_STRING_HPP_INCLUDED

View File

@@ -0,0 +1,39 @@
#ifndef BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED
// 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/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/enumerators.hpp>
#include <boost/mp11/algorithm.hpp>
namespace boost
{
namespace describe
{
template<class E, class De = describe_enumerators<E>>
char const * enum_to_string( E e, char const* def ) noexcept
{
char const * r = def;
mp11::mp_for_each<De>([&](auto D){
if( e == D.value ) r = D.name;
});
return r;
}
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_ENUM_TO_STRING_HPP_INCLUDED

View File

@@ -1,20 +1,42 @@
#ifndef BOOST_DESCRIBE_ENUMERATORS_HPP_INCLUDED
#define BOOST_DESCRIBE_ENUMERATORS_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// 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/detail/void_t.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
#include <type_traits>
namespace boost
{
namespace describe
{
template<class E> using describe_enumerators = decltype( _enum_descriptor_fn( static_cast<E*>(0) ) );
// describe_enumerators<E>
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E**>(0) ) );
// has_describe_enumerators<E>
namespace detail
{
template<class E, class En = void> struct has_describe_enumerators: std::false_type
{
};
template<class E> struct has_describe_enumerators<E, void_t<describe_enumerators<E>>>: std::true_type
{
};
} // namespace detail
template<class E> using has_describe_enumerators = detail::has_describe_enumerators<E>;
} // namespace describe
} // namespace boost

View File

@@ -7,6 +7,9 @@
#include <boost/describe/modifiers.hpp>
#include <boost/describe/bases.hpp>
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/cx_streq.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
@@ -15,6 +18,7 @@
#include <boost/mp11/integral.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/bind.hpp>
#include <type_traits>
namespace boost
{
@@ -25,9 +29,9 @@ namespace detail
// _describe_members<T>
template<class T> using _describe_public_members = decltype( _public_member_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_protected_members = decltype( _protected_member_descriptor_fn( static_cast<T*>(0) ) );
template<class T> using _describe_private_members = decltype( _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>>;
@@ -57,11 +61,6 @@ template<template<class...> class L, class T, class V> struct describe_inherited
using type = L<>;
};
constexpr bool cx_streq( char const * s1, char const * s2 )
{
return s1[0] == s2[0] && ( s1[0] == 0 || cx_streq( s1 + 1, s2 + 1 ) );
}
template<class D1, class D2> using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >;
template<class D, class L> using name_is_hidden = mp11::mp_any_of_q<L, mp11::mp_bind_front<name_matches, D>>;
@@ -129,17 +128,29 @@ template<class T, unsigned M> using describe_members = mp11::mp_eval_if_c<(M & m
template<unsigned M> struct member_filter
{
template<class T> using fn = mp11::mp_bool<
( M & mod_any_access & T::modifiers ) != 0 &&
( M & mod_static ) == ( T::modifiers & mod_static ) &&
( M & mod_function ) == ( T::modifiers & mod_function ) &&
( M & mod_hidden ) >= ( T::modifiers & mod_hidden )
(M & mod_any_access & T::modifiers) != 0 &&
( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) &&
( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) &&
(M & mod_hidden) >= (T::modifiers & mod_hidden)
>;
};
// has_describe_members
template<class T, class En = void> struct has_describe_members: std::false_type
{
};
template<class T> struct has_describe_members<T, void_t<_describe_members<T>>>: std::true_type
{
};
} // namespace detail
template<class T, unsigned M> using describe_members = mp11::mp_copy_if_q<detail::describe_members<T, M>, detail::member_filter<M>>;
template<class T> using has_describe_members = detail::has_describe_members<T>;
} // namespace describe
} // namespace boost

View File

@@ -20,8 +20,9 @@ enum modifiers
mod_virtual = 8,
mod_static = 16,
mod_function = 32,
mod_inherited = 64,
mod_hidden = 128,
mod_any_member = 64,
mod_inherited = 128,
mod_hidden = 256,
};
BOOST_DESCRIBE_ENUM(modifiers,
@@ -31,6 +32,7 @@ BOOST_DESCRIBE_ENUM(modifiers,
mod_virtual,
mod_static,
mod_function,
mod_any_member,
mod_inherited,
mod_hidden);

View File

@@ -0,0 +1,170 @@
#ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
#define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
// 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/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX14)
#include <boost/describe/bases.hpp>
#include <boost/describe/members.hpp>
#include <boost/describe/modifiers.hpp>
#include <boost/mp11/algorithm.hpp>
#include <type_traits>
#include <iosfwd>
namespace boost
{
namespace describe
{
namespace detail
{
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
bool eq( T const& t1, T const& t2 )
{
bool r = true;
mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
r = r && (B const&)t1 == (B const&)t2;
});
mp11::mp_for_each<Md>([&](auto D){
r = r && t1.*D.pointer == t2.*D.pointer;
});
return r;
}
template<class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
bool lt( T const& t1, T const& t2 )
{
int r = 0;
mp11::mp_for_each<Bd>([&](auto D){
using B = typename decltype(D)::type;
if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1;
if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1;
});
mp11::mp_for_each<Md>([&](auto D){
if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1;
if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1;
});
return r < 0;
}
template<class Os, class T,
class Bd = describe_bases<T, mod_any_access>,
class Md = describe_members<T, mod_any_access>>
void print( Os& os, T const& t )
{
os << "{";
bool first = true;
mp11::mp_for_each<Bd>([&](auto D){
if( !first ) { os << ", "; }
first = false;
using B = typename decltype(D)::type;
os << (B const&)t;
});
mp11::mp_for_each<Md>([&](auto D){
if( !first ) { os << ", "; }
first = false;
os << "." << D.name << " = " << t.*D.pointer;
});
os << "}";
}
} // namespace detail
namespace operators
{
template<class T> std::enable_if_t<
has_describe_bases<T>::value && has_describe_members<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>
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>
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>
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>
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>
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,
std::basic_ostream<Ch, Tr>&>
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
{
os.width( 0 );
detail::print( os, t );
return os;
}
} // namespace operators
} // namespace describe
} // namespace boost
#endif // defined(BOOST_DESCRIBE_CXX14)
#endif // #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED

View File

@@ -9,6 +9,7 @@
],
"description": "A C++14 reflection library.",
"category": [
"Emulation",
"Metaprogramming"
]
}

11
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,11 @@
# Copyright 2018, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::describe Boost::core)
endif()

View File

@@ -15,8 +15,17 @@ project : requirements
run quick.cpp ;
run pp_for_each_test.cpp ;
run pp_is_paren_test.cpp ;
run pp_is_empty_test.cpp ;
run pp_call_test.cpp ;
run pp_parse_test.cpp ;
run pp_name_test.cpp ;
run pp_pointer_test.cpp ;
run enumerators_test.cpp ;
run empty_enum_test.cpp ;
run trailing_comma_test.cpp ;
run nested_enum_test.cpp ;
run compute_base_modifiers.cpp ;
run bases_test.cpp ;
@@ -27,14 +36,44 @@ run members_test3.cpp ;
run members_test4.cpp ;
run members_test5.cpp ;
run members_test6.cpp ;
run members_test7.cpp : : : <toolset>msvc-14.0:<build>no ;
run members_test7.cpp
: : : <toolset>msvc-14.0:<build>no ;
run members_test8.cpp ;
run overloaded_test.cpp ;
run overloaded_test2.cpp ;
compile test_d_type.cpp ;
compile-fail enum_struct_fail.cpp ;
compile-fail struct_enum_fail.cpp ;
run class_template_test.cpp ;
run has_enumerators_test.cpp ;
run has_bases_test.cpp ;
run has_members_test.cpp ;
run enum_to_string_test.cpp ;
run enum_from_string_test.cpp ;
run operator_eq_test.cpp ;
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 ;
# examples
obj describe_cxx14 : describe_cxx14.cpp ;
explicit describe_cxx14 ;
local CXX14 = [ check-target-builds describe_cxx14 describe_cxx14 : : <build>no ] ;
local JSON = <library>/boost//json/<warnings>off "<toolset>msvc-14.0:<build>no" ;
local JSON = <library>/boost//json/<warnings>off "<toolset>msvc-14.0:<build>no" "<toolset>msvc-14.2:<cxxflags>-wd5104" ;
local SERIALIZATION = <library>/boost//serialization/<warnings>off "-<toolset>clang:<warnings-as-errors>on" ;
run ../example/printing_enums_ct.cpp : : : $(CXX14) ;
@@ -46,3 +85,7 @@ run ../example/to_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/from_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/serialization.cpp : : : $(CXX14) $(SERIALIZATION) ;
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) ;

View File

@@ -0,0 +1,143 @@
// 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/bases.hpp>
#include <boost/describe/members.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
template<class A1, class A2> struct X
{
A1 a1;
A2 a2;
BOOST_DESCRIBE_CLASS(X, (), (a1, a2), (), ())
};
template<class B1, class B2> class Y
{
private:
B1 b1;
B2 b2;
BOOST_DESCRIBE_CLASS(Y, (), (), (), (b1, b2))
};
template<class T1, class T2> class Z: public X<T1, T2>
{
private:
// error: declaration of 'typedef struct X<T1, T2> Z<T1, T2>::X' changes meaning of 'X' (g++)
// typedef X<T1, T2> X;
typedef X<T1, T2> XB;
protected:
Y<T1, T2> y;
BOOST_DESCRIBE_CLASS(Z, (XB), (), (y), ())
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#elif defined(BOOST_MSVC) && BOOST_MSVC < 1920
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is below 1920")
int main() {}
#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1920 && BOOST_MSVC < 1940 && _MSVC_LANG <= 201703L
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is 192x or 193x and _MSVC_LANG is 201703L or below")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
using namespace boost::describe;
using namespace boost::mp11;
{
using L = describe_members<X<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
BOOST_TEST( D1::pointer == (&X<int, float>::a1) );
BOOST_TEST_CSTR_EQ( D1::name, "a1" );
BOOST_TEST_EQ( D1::modifiers, mod_public );
BOOST_TEST( D2::pointer == (&X<int, float>::a2) );
BOOST_TEST_CSTR_EQ( D2::name, "a2" );
BOOST_TEST_EQ( D2::modifiers, mod_public );
}
{
using L = describe_members<Y<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
// BOOST_TEST( D1::pointer == (&Y<int, float>::b1) );
BOOST_TEST_CSTR_EQ( D1::name, "b1" );
BOOST_TEST_EQ( D1::modifiers, mod_private );
// BOOST_TEST( D2::pointer == (&Y<int, float>::b2) );
BOOST_TEST_CSTR_EQ( D2::name, "b2" );
BOOST_TEST_EQ( D2::modifiers, mod_private );
}
{
using L = describe_members<Z<int, float>, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 1 );
using D1 = mp_at_c<L, 0>;
// BOOST_TEST( D1::pointer == (&Z<int, float>::y) );
BOOST_TEST_CSTR_EQ( D1::name, "y" );
BOOST_TEST_EQ( D1::modifiers, mod_protected );
}
{
using L = describe_members<Z<int, float>, mod_any_access | mod_inherited>;
BOOST_TEST_EQ( mp_size<L>::value, 3 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
using D3 = mp_at_c<L, 2>;
BOOST_TEST( D1::pointer == (&X<int, float>::a1) );
BOOST_TEST_CSTR_EQ( D1::name, "a1" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_inherited );
BOOST_TEST( D2::pointer == (&X<int, float>::a2) );
BOOST_TEST_CSTR_EQ( D2::name, "a2" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_inherited );
// BOOST_TEST( D3::pointer == (&Z<int, float>::y) );
BOOST_TEST_CSTR_EQ( D3::name, "y" );
BOOST_TEST_EQ( D3::modifiers, mod_protected );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,64 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/descriptor_by_name.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/members.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
struct X
{
int a = 1;
int b = 2;
};
BOOST_DESCRIBE_STRUCT(X, (), (a, b))
struct Y
{
int a = 1;
int c = 3;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a, c))
int main()
{
{
using L = boost::describe::describe_members<X, boost::describe::mod_any_access>;
using Na = BOOST_DESCRIBE_MAKE_NAME( a );
using Da = boost::describe::descriptor_by_name<L, Na>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Nb = BOOST_DESCRIBE_MAKE_NAME( b );
using Db = boost::describe::descriptor_by_name<L, Nb>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
}
{
using L = boost::describe::describe_members<Y, boost::describe::mod_any_access>;
using Na = BOOST_DESCRIBE_MAKE_NAME( a );
using Da = boost::describe::descriptor_by_name<L, Na>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Nc = BOOST_DESCRIBE_MAKE_NAME( c );
using Dc = boost::describe::descriptor_by_name<L, Nc>;
BOOST_TEST_CSTR_EQ( Dc::name, "c" );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,65 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/descriptor_by_pointer.hpp>
#include <boost/describe/class.hpp>
#include <boost/describe/members.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(__cpp_nontype_template_parameter_auto) || __cpp_nontype_template_parameter_auto < 201606L
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because __cpp_nontype_template_parameter_auto is not defined")
int main() {}
#else
struct X
{
int a = 1;
float b = 3.14f;
};
BOOST_DESCRIBE_STRUCT(X, (), (a, b))
struct Y: public X
{
long a = 2;
double c = 3.14;
};
BOOST_DESCRIBE_STRUCT(Y, (X), (a, c))
int main()
{
using namespace boost::describe;
{
using L = describe_members<X, mod_any_access>;
using Da = descriptor_by_pointer<L, &X::a>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Db = descriptor_by_pointer<L, &X::b>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
}
{
using L = describe_members<Y, mod_any_access | mod_inherited>;
using Da = descriptor_by_pointer<L, &Y::a>;
BOOST_TEST_CSTR_EQ( Da::name, "a" );
using Db = descriptor_by_pointer<L, &Y::b>;
BOOST_TEST_CSTR_EQ( Db::name, "b" );
using Dc = descriptor_by_pointer<L, &Y::c>;
BOOST_TEST_CSTR_EQ( Dc::name, "c" );
}
return boost::report_errors();
}
#endif // __cpp_nontype_template_parameter_auto

41
test/empty_enum_test.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
enum E1 {};
BOOST_DESCRIBE_ENUM(E1)
BOOST_DEFINE_ENUM(E2)
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D1 = boost::describe::describe_enumerators<E1>;
BOOST_TEST_EQ( mp_size<D1>::value, 0 );
}
{
using D2 = boost::describe::describe_enumerators<E2>;
BOOST_TEST_EQ( mp_size<D2>::value, 0 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,62 @@
// 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_from_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
enum E1 { v101 = 101, v102 = 102 };
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_CLASS(E4, v401, v402)
int main()
{
using boost::describe::enum_from_string;
{
E1 w{};
BOOST_TEST( enum_from_string( "v101", w ) ) && BOOST_TEST_EQ( w, v101 );
BOOST_TEST( enum_from_string( "v102", w ) ) && BOOST_TEST_EQ( w, v102 );
BOOST_TEST_NOT( enum_from_string( "v103", w ) );
}
{
E2 w{};
BOOST_TEST( enum_from_string( "v201", w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v201 );
BOOST_TEST( enum_from_string( "v202", w ) ) && BOOST_TEST_EQ( (int)w, (int)E2::v202 );
BOOST_TEST_NOT( enum_from_string( "v203", w ) );
}
{
E3 w{};
BOOST_TEST( enum_from_string( "v301", w ) ) && BOOST_TEST_EQ( w, v301 );
BOOST_TEST( enum_from_string( "v302", w ) ) && BOOST_TEST_EQ( w, v302 );
BOOST_TEST_NOT( enum_from_string( "v303", w ) );
}
{
E4 w{};
BOOST_TEST( enum_from_string( "v401", w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v401 );
BOOST_TEST( enum_from_string( "v402", w ) ) && BOOST_TEST_EQ( (int)w, (int)E4::v402 );
BOOST_TEST_NOT( enum_from_string( "v403", w ) );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

16
test/enum_struct_fail.cpp Normal file
View 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/class.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#error "Skipping test because C++14 is not available"
#else
enum E1 {};
BOOST_DESCRIBE_STRUCT(E1, (), ())
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -0,0 +1,41 @@
// 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_to_string.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
enum E1 { v1 };
BOOST_DESCRIBE_ENUM(E1, v1)
enum class E2 { v2 };
BOOST_DESCRIBE_ENUM(E2, v2)
BOOST_DEFINE_ENUM(E3, v3);
BOOST_DEFINE_ENUM_CLASS(E4, v4)
int main()
{
using boost::describe::enum_to_string;
BOOST_TEST_CSTR_EQ( enum_to_string( v1, "" ), "v1" );
BOOST_TEST_CSTR_EQ( enum_to_string( E2::v2, "" ), "v2" );
BOOST_TEST_CSTR_EQ( enum_to_string( static_cast<E2>( 14 ), "__def__" ), "__def__" );
BOOST_TEST_CSTR_EQ( enum_to_string( v3, "" ), "v3" );
BOOST_TEST_CSTR_EQ( enum_to_string( E4::v4, "" ), "v4" );
BOOST_TEST_EQ( enum_to_string( static_cast<E4>( 14 ), 0 ), static_cast<char const*>( 0 ) );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View File

@@ -6,6 +6,37 @@
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
enum E1
{
v1_1 = 5
};
BOOST_DESCRIBE_ENUM(E1, v1_1);
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3);
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
enum class E2
{
v2_1,
v2_2 = 7
};
BOOST_DESCRIBE_ENUM(E2, v2_1, v2_2);
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);
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
@@ -15,27 +46,6 @@ int main() {}
#else
enum E1
{
v1_1 = 5
};
BOOST_DESCRIBE_ENUM(E1, v1_1);
enum class E2
{
v2_1,
v2_2 = 7
};
BOOST_DESCRIBE_ENUM_CLASS(E2, v2_1, v2_2);
BOOST_DEFINE_ENUM(E3, v3_1, v3_2, v3_3);
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);
#include <boost/mp11.hpp>
using namespace boost::mp11;
@@ -144,3 +154,4 @@ int main()
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

60
test/has_bases_test.cpp Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/bases.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X1 {};
BOOST_DESCRIBE_STRUCT(X1, (), ())
class X2
{
BOOST_DESCRIBE_CLASS(X2, (), (), (), ())
};
struct X3 {};
class X4 {};
union X5 {};
struct X6: X1 {};
struct X7: X2 {};
int main()
{
using boost::describe::has_describe_bases;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_bases<X1>));
BOOST_TEST_TRAIT_TRUE((has_describe_bases<X2>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X1>));
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X2>));
#endif
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>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -0,0 +1,58 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
enum E1 { v1 };
BOOST_DESCRIBE_ENUM(E1, v1)
enum class E2 { v2 };
BOOST_DESCRIBE_ENUM(E2, v2)
BOOST_DEFINE_ENUM(E3, v3);
BOOST_DEFINE_ENUM_CLASS(E4, v4)
enum E5 { v5 };
enum class E6 { v6 };
int main()
{
using boost::describe::has_describe_enumerators;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E1>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E2>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E3>));
BOOST_TEST_TRAIT_TRUE((has_describe_enumerators<E4>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E1>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E2>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E3>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E4>));
#endif
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E5>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<E6>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<int>));
BOOST_TEST_TRAIT_FALSE((has_describe_enumerators<void>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

60
test/has_members_test.cpp Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 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_trait.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X1 {};
BOOST_DESCRIBE_STRUCT(X1, (), ())
class X2
{
BOOST_DESCRIBE_CLASS(X2, (), (), (), ())
};
struct X3 {};
class X4 {};
union X5 {};
struct X6: X1 {};
struct X7: X2 {};
int main()
{
using boost::describe::has_describe_members;
#if defined(BOOST_DESCRIBE_CXX14)
BOOST_TEST_TRAIT_TRUE((has_describe_members<X1>));
BOOST_TEST_TRAIT_TRUE((has_describe_members<X2>));
#else
BOOST_TEST_TRAIT_FALSE((has_describe_members<X1>));
BOOST_TEST_TRAIT_FALSE((has_describe_members<X2>));
#endif
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>));
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

View File

@@ -40,7 +40,7 @@ private:
BOOST_DESCRIBE_CLASS(A2, (), (m1), (m2), (m3))
};
struct B: public A1, private A2
class A3
{
public:
@@ -54,7 +54,24 @@ private:
int m3;
BOOST_DESCRIBE_CLASS(B, (A1, A2), (m1), (m2), (m3))
BOOST_DESCRIBE_CLASS(A3, (), (m1), (m2), (m3))
};
struct B: public A1, protected A2, private A3
{
public:
int m1;
protected:
int m2;
private:
int m3;
BOOST_DESCRIBE_CLASS(B, (A1, A2, A3), (m1), (m2), (m3))
};
#if !defined(BOOST_DESCRIBE_CXX14)
@@ -93,50 +110,65 @@ int main()
{
using L = describe_members<B, mod_protected | mod_inherited | mod_hidden>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
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 == &B::A1::m2 );
BOOST_TEST_CSTR_EQ( D1::name, "m2" );
BOOST_TEST_EQ( D1::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D2::pointer == &B::m2 );
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
BOOST_TEST_EQ( D2::modifiers, mod_protected );
// BOOST_TEST( D2::pointer == &B::A2::m1 );
BOOST_TEST_CSTR_EQ( D2::name, "m1" );
BOOST_TEST_EQ( D2::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D3::pointer == &B::A2::m2 );
BOOST_TEST_CSTR_EQ( D3::name, "m2" );
BOOST_TEST_EQ( D3::modifiers, mod_protected | mod_inherited | mod_hidden );
// BOOST_TEST( D4::pointer == &B::m2 );
BOOST_TEST_CSTR_EQ( D4::name, "m2" );
BOOST_TEST_EQ( D4::modifiers, mod_protected );
}
{
using L = describe_members<B, mod_private | mod_inherited | mod_hidden>;
BOOST_TEST_EQ( mp_size<L>::value, 5 );
BOOST_TEST_EQ( mp_size<L>::value, 6 );
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>;
using D5 = mp_at_c<L, 4>;
using D6 = mp_at_c<L, 5>;
// BOOST_TEST( D1::pointer == &B::A1::m3 );
BOOST_TEST_CSTR_EQ( D1::name, "m3" );
BOOST_TEST_EQ( D1::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D2::pointer == &B::A2::m1 );
BOOST_TEST_CSTR_EQ( D2::name, "m1" );
// BOOST_TEST( D2::pointer == &B::A2::m3 );
BOOST_TEST_CSTR_EQ( D2::name, "m3" );
BOOST_TEST_EQ( D2::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D3::pointer == &B::A2::m2 );
BOOST_TEST_CSTR_EQ( D3::name, "m2" );
// BOOST_TEST( D3::pointer == &B::A3::m1 );
BOOST_TEST_CSTR_EQ( D3::name, "m1" );
BOOST_TEST_EQ( D3::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D4::pointer == &B::A2::m3 );
BOOST_TEST_CSTR_EQ( D4::name, "m3" );
// BOOST_TEST( D4::pointer == &B::A3::m2 );
BOOST_TEST_CSTR_EQ( D4::name, "m2" );
BOOST_TEST_EQ( D4::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D5::pointer == &B::m3 );
// BOOST_TEST( D5::pointer == &B::A3::m3 );
BOOST_TEST_CSTR_EQ( D5::name, "m3" );
BOOST_TEST_EQ( D5::modifiers, mod_private );
BOOST_TEST_EQ( D5::modifiers, mod_private | mod_inherited | mod_hidden );
// BOOST_TEST( D6::pointer == &B::m3 );
BOOST_TEST_CSTR_EQ( D6::name, "m3" );
BOOST_TEST_EQ( D6::modifiers, mod_private );
}
return boost::report_errors();

View File

@@ -59,7 +59,7 @@ int main()
using D1 = mp_at_c<L, 0>;
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
// https://developercommunity.visualstudio.com/content/problem/1186002/constexpr-pointer-to-member-has-incorrect-value.html
BOOST_TEST( D1::pointer == &C::m2 );
#endif
@@ -79,7 +79,7 @@ int main()
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_inherited );
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
BOOST_TEST( D2::pointer == &C::m2 );
#endif
BOOST_TEST_CSTR_EQ( D2::name, "m2" );

67
test/members_test8.cpp Normal file
View File

@@ -0,0 +1,67 @@
// 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>
struct 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)
#include <boost/config/pragma_message.hpp>
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)

130
test/nested_enum_test.cpp Normal file
View File

@@ -0,0 +1,130 @@
// 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/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
struct X1
{
enum E
{
v1 = 5
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1)
};
class X2
{
private:
enum E
{
v1, v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
typedef E E2;
};
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
struct X3
{
enum class E
{
v1 = 7
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1)
};
class X4
{
private:
enum class E
{
v1, v2
};
BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2)
public:
typedef E E2;
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D = boost::describe::describe_enumerators<X1::E>;
BOOST_TEST_EQ( mp_size<D>::value, 1 );
BOOST_TEST_EQ( (mp_at_c<D, 0>::value), X1::v1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
}
{
using D = boost::describe::describe_enumerators<X2::E2>;
BOOST_TEST_EQ( mp_size<D>::value, 2 );
BOOST_TEST_EQ( (mp_at_c<D, 0>::value), 0 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
BOOST_TEST_EQ( (mp_at_c<D, 1>::value), 1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 1>::name), "v2" );
}
{
using D = boost::describe::describe_enumerators<X3::E>;
BOOST_TEST_EQ( mp_size<D>::value, 1 );
BOOST_TEST_EQ( (int)(mp_at_c<D, 0>::value), (int)X3::E::v1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
}
{
using D = boost::describe::describe_enumerators<X4::E2>;
BOOST_TEST_EQ( mp_size<D>::value, 2 );
BOOST_TEST_EQ( (int)(mp_at_c<D, 0>::value), 0 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 0>::name), "v1" );
BOOST_TEST_EQ( (int)(mp_at_c<D, 1>::value), 1 );
BOOST_TEST_CSTR_EQ( (mp_at_c<D, 1>::name), "v2" );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)
#endif // !defined(BOOST_DESCRIBE_CXX11)

91
test/operator_eq_test.cpp Normal file
View File

@@ -0,0 +1,91 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/operators.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
namespace app
{
struct X
{
};
BOOST_DESCRIBE_STRUCT(X, (), ())
using boost::describe::operators::operator==;
using boost::describe::operators::operator<<;
struct Y
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
struct Z: X, Y
{
int b = 4;
};
BOOST_DESCRIBE_STRUCT(Z, (X, Y), (b))
using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;
} // namespace app
int main()
{
using app::X;
{
X x1, x2;
BOOST_TEST_EQ( x1, x2 );
}
using app::Y;
{
Y y1, y2, y3;
y3.a = 2;
BOOST_TEST_EQ( y1, y2 );
BOOST_TEST_NE( y1, y3 );
}
using app::Z;
{
Z z1, z2, z3, z4;
z3.a = 2;
z4.b = 3;
BOOST_TEST_EQ( z1, z2 );
BOOST_TEST_NE( z1, z3 );
BOOST_TEST_NE( z1, z4 );
BOOST_TEST_NE( z3, z4 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

99
test/operator_lt_test.cpp Normal file
View File

@@ -0,0 +1,99 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/operators.hpp>
#include <boost/describe/class.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
namespace app
{
struct X
{
};
BOOST_DESCRIBE_STRUCT(X, (), ())
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
struct Y
{
int a = 1;
};
BOOST_DESCRIBE_STRUCT(Y, (), (a))
using boost::describe::operators::operator<;
using boost::describe::operators::operator>;
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
struct Z: X, Y
{
int b = 4;
};
BOOST_DESCRIBE_STRUCT(Z, (X, Y), (b))
using boost::describe::operators::operator<;
using boost::describe::operators::operator>;
using boost::describe::operators::operator<=;
using boost::describe::operators::operator>=;
using boost::describe::operators::operator<<;
} // namespace app
#define TEST_EQ(x, y) BOOST_TEST_LE(x, y); BOOST_TEST_GE(x, y); BOOST_TEST_NOT((x) < (y)); BOOST_TEST_NOT((x) > (y))
#define TEST_LT(x, y) BOOST_TEST_LT(x, y); BOOST_TEST_LE(x, y); BOOST_TEST_GT(y, x); BOOST_TEST_GE(y, x)
int main()
{
using app::X;
{
X x1, x2;
TEST_EQ( x1, x2 );
}
using app::Y;
{
Y y1, y2, y3;
y3.a = 2;
TEST_EQ( y1, y2 );
TEST_LT( y1, y3 );
}
using app::Z;
{
Z z1, z2, z3, z4;
z3.a = 2;
z4.b = 3;
TEST_EQ( z1, z2 );
TEST_LT( z1, z3 );
TEST_LT( z4, z1 );
TEST_LT( z4, z3 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

82
test/overloaded_test.cpp Normal file
View File

@@ -0,0 +1,82 @@
// Copyright 2020 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>
struct X
{
int f() { return 1; }
int f() const { return 2; }
static int f( int x ) { return x; }
static int f( int x, int y ) { return x + y; }
};
BOOST_DESCRIBE_STRUCT(X, (), (
(int ()) f,
(int () const) f,
(int (int)) f,
(int (int, int)) f
))
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
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<X, mod_any_access | mod_function>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
X x;
BOOST_TEST_EQ( (x.*D1::pointer)(), 1 );
BOOST_TEST_CSTR_EQ( D1::name, "f" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_function );
BOOST_TEST_EQ( (x.*D2::pointer)(), 2 );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_function );
}
{
using L = describe_members<X, mod_any_access | mod_static | mod_function>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
using D1 = mp_at_c<L, 0>;
using D1 = mp_at_c<L, 0>;
using D2 = mp_at_c<L, 1>;
BOOST_TEST_EQ( (*D1::pointer)( 3 ), 3 );
BOOST_TEST_CSTR_EQ( D1::name, "f" );
BOOST_TEST_EQ( D1::modifiers, mod_public | mod_static | mod_function );
BOOST_TEST_EQ( (*D2::pointer)( 4, 5 ), 9 );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

74
test/overloaded_test2.cpp Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2020 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 <utility>
class X
{
private:
std::pair<int, int> p_;
public:
std::pair<int, int>& f() { return p_; }
std::pair<int, int> const& f() const { return p_; }
BOOST_DESCRIBE_CLASS(X, (), ((std::pair<int, int>& ()) f, (std::pair<int, int> const& () const) f), (), (p_))
};
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
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 L1 = describe_members<X, mod_any_access>;
BOOST_TEST_EQ( mp_size<L1>::value, 1 );
using D1 = mp_at_c<L1, 0>;
BOOST_TEST_CSTR_EQ( D1::name, "p_" );
BOOST_TEST_EQ( D1::modifiers, mod_private );
X x;
auto& p = x.*D1::pointer;
using L2 = describe_members<X, mod_any_access | mod_function>;
BOOST_TEST_EQ( mp_size<L2>::value, 2 );
using D2 = mp_at_c<L2, 0>;
using D3 = mp_at_c<L2, 1>;
BOOST_TEST_EQ( &(x.*D2::pointer)(), &p );
BOOST_TEST_CSTR_EQ( D2::name, "f" );
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_function );
BOOST_TEST_EQ( &(x.*D3::pointer)(), &p );
BOOST_TEST_CSTR_EQ( D3::name, "f" );
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

43
test/pp_call_test.cpp Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
#define F(a, x) (a, x)
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_CALL(F, a, x));
char const * s2 = "" S(BOOST_DESCRIBE_PP_CALL(F, a, ));
char const * s3 = S(BOOST_DESCRIBE_PP_CALL(F, a, () x));
char const * s4 = S(BOOST_DESCRIBE_PP_CALL(F, a, (b, c) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "(a, x)" );
BOOST_TEST_CSTR_EQ( s2, "" );
BOOST_TEST_CSTR_EQ( s3, "(a, () x)" );
BOOST_TEST_CSTR_EQ( s4, "(a, (b, c) x)" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

40
test/pp_is_empty_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) #x
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_IS_EMPTY());
char const * s2 = S(BOOST_DESCRIBE_PP_IS_EMPTY(x));
char const * s3 = S(BOOST_DESCRIBE_PP_IS_EMPTY(() x));
char const * s4 = S(BOOST_DESCRIBE_PP_IS_EMPTY((a, b) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "1" );
BOOST_TEST_CSTR_EQ( s2, "0" );
BOOST_TEST_CSTR_EQ( s3, "0" );
BOOST_TEST_CSTR_EQ( s4, "0" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

41
test/pp_is_paren_test.cpp Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
char const * s1 = S(BOOST_DESCRIBE_PP_IS_PAREN());
char const * s2 = S(BOOST_DESCRIBE_PP_IS_PAREN(x));
char const * s3 = S(BOOST_DESCRIBE_PP_IS_PAREN(() x));
char const * s4 = S(BOOST_DESCRIBE_PP_IS_PAREN((a, b) x));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "0" );
BOOST_TEST_CSTR_EQ( s2, "0" );
BOOST_TEST_CSTR_EQ( s3, "1" );
BOOST_TEST_CSTR_EQ( s4, "1" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

33
test/pp_name_test.cpp Normal file
View File

@@ -0,0 +1,33 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
char const * s1 = BOOST_DESCRIBE_PP_NAME(x);
char const * s2 = BOOST_DESCRIBE_PP_NAME(() y);
char const * s3 = BOOST_DESCRIBE_PP_NAME((a) z);
char const * s4 = BOOST_DESCRIBE_PP_NAME((a, b) w);
int main()
{
BOOST_TEST_CSTR_EQ( s1, "x" );
BOOST_TEST_CSTR_EQ( s2, "y" );
BOOST_TEST_CSTR_EQ( s3, "z" );
BOOST_TEST_CSTR_EQ( s4, "w" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

37
test/pp_parse_test.cpp Normal file
View File

@@ -0,0 +1,37 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) #x
char const * s1 = S((BOOST_DESCRIBE_PP_PARSE(x)));
char const * s2 = S((BOOST_DESCRIBE_PP_PARSE(() y)));
char const * s3 = S((BOOST_DESCRIBE_PP_PARSE((a) z)));
char const * s4 = S((BOOST_DESCRIBE_PP_PARSE((a, b) w)));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "(0, ~, x)" );
BOOST_TEST_CSTR_EQ( s2, "(1, (), y)" );
BOOST_TEST_CSTR_EQ( s3, "(1, (a), z)" );
BOOST_TEST_CSTR_EQ( s4, "(1, (a, b), w)" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

40
test/pp_pointer_test.cpp Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/pp_utilities.hpp>
#include <boost/describe/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if !defined(BOOST_DESCRIBE_CXX11)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
int main() {}
#else
#define S(x) S2(x)
#define S2(x) S3(x)
#define S3(x) S4(x)
#define S4(x) #x
char const * s1 = S(BOOST_DESCRIBE_PP_POINTER(C1, x));
char const * s2 = S((BOOST_DESCRIBE_PP_POINTER(C2, (R ()) y)));
char const * s3 = S((BOOST_DESCRIBE_PP_POINTER(C3, (R () const) z)));
char const * s4 = S((BOOST_DESCRIBE_PP_POINTER(C4, (R (A1)) v)));
char const * s5 = S((BOOST_DESCRIBE_PP_POINTER(C5, (R (A1, A2) const &&) w)));
int main()
{
BOOST_TEST_CSTR_EQ( s1, "&C1::x" );
BOOST_TEST_CSTR_EQ( s2, "(::boost::describe::detail::mfn<C2, R ()>(&C2::y))" );
BOOST_TEST_CSTR_EQ( s3, "(::boost::describe::detail::mfn<C3, R () const>(&C3::z))" );
BOOST_TEST_CSTR_EQ( s4, "(::boost::describe::detail::mfn<C4, R (A1)>(&C4::v))" );
BOOST_TEST_CSTR_EQ( s5, "(::boost::describe::detail::mfn<C5, R (A1, A2) const &&>(&C5::w))" );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX11)

16
test/struct_enum_fail.cpp Normal file
View 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
struct X {};
BOOST_DESCRIBE_ENUM(X)
#endif // !defined(BOOST_DESCRIBE_CXX14)

76
test/test_d_type.cpp Normal file
View File

@@ -0,0 +1,76 @@
// 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>
#include <boost/describe/class.hpp>
namespace N1
{
enum D
{
d
};
BOOST_DESCRIBE_ENUM(D, d)
}
namespace N2
{
enum E
{
D
};
BOOST_DESCRIBE_ENUM(E, D)
}
namespace N3
{
struct D
{
int d;
};
BOOST_DESCRIBE_STRUCT(D, (), (d))
}
namespace N4
{
struct E
{
int D;
};
BOOST_DESCRIBE_STRUCT(E, (), (D))
}
namespace N5
{
class D
{
int d;
BOOST_DESCRIBE_CLASS(D, (), (), (), (d))
};
}
namespace N6
{
struct D {};
struct E: D {};
BOOST_DESCRIBE_STRUCT(E, (D), ())
}
namespace N7
{
struct D {};
class E: D
{
int d;
BOOST_DESCRIBE_CLASS(E, (D), (), (), (d))
};
}
int main()
{
}

View 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/enumerators.hpp>
#include <boost/describe/enum.hpp>
#include <boost/core/lightweight_test.hpp>
#if defined(_MSC_VER)
# pragma warning(disable: 4003) // not enough arguments for macro invocation
#endif
enum E1 { a1, b1, c1, };
BOOST_DESCRIBE_ENUM(E1, a1, b1, c1, )
BOOST_DEFINE_ENUM(E2, a2, b2, c2, )
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/mp11.hpp>
using namespace boost::mp11;
int main()
{
{
using D1 = boost::describe::describe_enumerators<E1>;
BOOST_TEST_EQ( mp_size<D1>::value, 3 );
}
{
using D2 = boost::describe::describe_enumerators<E2>;
BOOST_TEST_EQ( mp_size<D2>::value, 3 );
}
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)

View 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)

View 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)