Compare commits

...

38 Commits

Author SHA1 Message Date
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
42 changed files with 1610 additions and 2009 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,11 @@ 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: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
@@ -195,4 +197,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

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,13 +2,12 @@
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
* GCC 5 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
@@ -17,4 +16,5 @@ Tested on [Travis](https://travis-ci.org/github/pdimov/describe/) and
## 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

@@ -10,10 +10,13 @@ Peter Dimov
:toclevels: 4
:idprefix:
: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[]

13
doc/describe/changes.adoc Normal file
View File

@@ -0,0 +1,13 @@
////
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`.

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`).
@@ -75,7 +86,7 @@ excludes them. The other two modifiers work similarly.
`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`.
@@ -88,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
@@ -121,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

@@ -47,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

@@ -86,12 +86,43 @@ change its state and hence cannot violate its invariant.)
include::../../example/print_function.cpp[lines=5..-1]
----
[#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]
----
[#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 +167,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 +175,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,8 +14,7 @@ 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
* GCC 5 or later with `-std=c++14` or above
* Clang 3.6 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
@@ -31,8 +30,6 @@ This implementation has the following limitations:
* Protected base classes cannot be distinguished from private
base classes when the described class is final, and are considered
private.
* Overloaded member functions are not supported. Member names
must be unique within the class.
* 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

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,6 +49,13 @@ struct Di
```
where `vi` is the corresponding identifier passed to the macro.
### BOOST_DESCRIBE_NESTED_ENUM
`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
`BOOST_DEFINE_ENUM(E, v1, v2, ..., vN)` is a convenience macro expanding to
@@ -88,6 +96,8 @@ namespace describe {
template<class E> using describe_enumerators = /*...*/;
template<class E> using has_describe_enumerators = /*...*/;
} }
```
@@ -108,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>
```
@@ -190,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 );
@@ -211,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
@@ -222,6 +242,8 @@ namespace describe {
template<class T, unsigned M> using describe_bases = /*...*/;
template<class T> using has_describe_bases = /*...*/;
} }
```
@@ -247,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>
```
@@ -255,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
@@ -284,6 +320,18 @@ 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.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

@@ -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
{
@@ -26,10 +28,20 @@ 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) \
@@ -58,6 +60,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) \

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,9 +44,12 @@ template<unsigned M, class... T> auto member_descriptor_fn_impl( int, T... )
return list<member_descriptor<T, M>...>();
}
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 &C::m; } \
static constexpr auto name() noexcept { return #m; } }; return _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__)

View File

@@ -45,4 +45,48 @@
#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,16 +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_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
@@ -53,17 +56,31 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
#if defined(_MSC_VER) && !defined(__clang__)
#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_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)
#endif
} // namespace describe

View File

@@ -1,21 +1,43 @@
#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
{
// 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,8 @@
#include <boost/describe/modifiers.hpp>
#include <boost/describe/bases.hpp>
#include <boost/describe/detail/void_t.hpp>
#include <boost/describe/detail/config.hpp>
#if defined(BOOST_DESCRIBE_CXX11)
@@ -15,6 +17,7 @@
#include <boost/mp11/integral.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/bind.hpp>
#include <type_traits>
namespace boost
{
@@ -129,17 +132,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);

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

@@ -18,10 +18,14 @@ 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 ;
@@ -32,16 +36,32 @@ 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 ;
# 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) ;
@@ -53,3 +73,6 @@ 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) ;

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 < 1930 && _MSVC_LANG <= 201703L
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is 192x 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)

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)

55
test/has_bases_test.cpp Normal file
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/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 {};
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<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)

55
test/has_members_test.cpp Normal file
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/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 {};
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<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();

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)

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)

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)