mirror of
https://github.com/boostorg/describe.git
synced 2026-01-23 05:22:18 +00:00
Compare commits
25 Commits
boost-1.77
...
feature/de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fc0e817ad | ||
|
|
84fe8aa21e | ||
|
|
003b2bdc50 | ||
|
|
8437f2e62e | ||
|
|
448174f346 | ||
|
|
2935bca3b1 | ||
|
|
e407d4da19 | ||
|
|
2accb05ce5 | ||
|
|
128e3667d6 | ||
|
|
8cf28d7b6e | ||
|
|
7397e8d66a | ||
|
|
c3f16f3332 | ||
|
|
890c1afcda | ||
|
|
caa4cb6bf0 | ||
|
|
ffa4790292 | ||
|
|
f7d2f12cd4 | ||
|
|
53d577428e | ||
|
|
9c351a463f | ||
|
|
af01484087 | ||
|
|
d5e79ee67d | ||
|
|
300ea0bebe | ||
|
|
5a4c425f32 | ||
|
|
fe23aeeee4 | ||
|
|
daaec68db6 | ||
|
|
b6c41956ec |
58
.github/workflows/ci.yml
vendored
58
.github/workflows/ci.yml
vendored
@@ -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"
|
||||
@@ -41,48 +38,29 @@ jobs:
|
||||
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
|
||||
os: ubuntu-20.04
|
||||
install: g++-10
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
install: g++-11
|
||||
- toolset: clang
|
||||
compiler: clang++-3.5
|
||||
cxxstd: "03,11"
|
||||
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
|
||||
- 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
|
||||
@@ -96,7 +74,7 @@ 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
|
||||
@@ -108,14 +86,17 @@ jobs:
|
||||
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
|
||||
@@ -180,6 +161,15 @@ jobs:
|
||||
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
|
||||
|
||||
@@ -8,10 +8,10 @@ for more information and usage examples.
|
||||
## Supported Compilers
|
||||
|
||||
* GCC 5 or later with `-std=c++14` or above
|
||||
* Clang 3.6 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
|
||||
|
||||
@@ -9,6 +9,7 @@ Peter Dimov
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:idprefix:
|
||||
:listing-caption: Code Example
|
||||
:docinfo: private-footer
|
||||
:source-highlighter: rouge
|
||||
:source-language: c++
|
||||
@@ -16,6 +17,7 @@ Peter Dimov
|
||||
: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
16
doc/describe/changes.adoc
Normal file
@@ -0,0 +1,16 @@
|
||||
////
|
||||
Copyright 2021 Peter Dimov
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
https://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
[#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`.
|
||||
@@ -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].
|
||||
|
||||
@@ -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,6 +85,27 @@ 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
|
||||
|
||||
@@ -117,6 +137,30 @@ to all annotated classes also defined in `app`.
|
||||
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_to_json]
|
||||
## Automatic Conversion to JSON
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ https://boost.org/libs/mp11[Boost.Mp11].
|
||||
## Supported Compilers
|
||||
|
||||
* GCC 5 or later with `-std=c++14` or above
|
||||
* Clang 3.6 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
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ namespace describe {
|
||||
|
||||
template<class E> using describe_enumerators = /*...*/;
|
||||
|
||||
template<class E> using has_describe_enumerators = /*...*/;
|
||||
|
||||
} }
|
||||
```
|
||||
|
||||
@@ -116,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>
|
||||
|
||||
```
|
||||
@@ -232,6 +242,8 @@ namespace describe {
|
||||
|
||||
template<class T, unsigned M> using describe_bases = /*...*/;
|
||||
|
||||
template<class T> using has_describe_bases = /*...*/;
|
||||
|
||||
} }
|
||||
```
|
||||
|
||||
@@ -257,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>
|
||||
|
||||
```
|
||||
@@ -265,6 +289,8 @@ namespace describe {
|
||||
|
||||
template<class T, unsigned M> using describe_members = /*...*/;
|
||||
|
||||
template<class T> using has_describe_members = /*...*/;
|
||||
|
||||
} }
|
||||
```
|
||||
|
||||
@@ -294,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/enum_to_string.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/enum_from_string.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/descriptor_by_name.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/descriptor_by_pointer.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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
41
include/boost/describe/descriptor_by_name.hpp
Normal file
41
include/boost/describe/descriptor_by_name.hpp
Normal 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
|
||||
48
include/boost/describe/descriptor_by_pointer.hpp
Normal file
48
include/boost/describe/descriptor_by_pointer.hpp
Normal 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
|
||||
30
include/boost/describe/detail/cx_streq.hpp
Normal file
30
include/boost/describe/detail/cx_streq.hpp
Normal 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
|
||||
32
include/boost/describe/detail/void_t.hpp
Normal file
32
include/boost/describe/detail/void_t.hpp
Normal 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
|
||||
44
include/boost/describe/enum_from_string.hpp
Normal file
44
include/boost/describe/enum_from_string.hpp
Normal 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
|
||||
39
include/boost/describe/enum_to_string.hpp
Normal file
39
include/boost/describe/enum_to_string.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -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>>;
|
||||
@@ -136,10 +135,22 @@ template<unsigned M> struct member_filter
|
||||
>;
|
||||
};
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
170
include/boost/describe/operators.hpp
Normal file
170
include/boost/describe/operators.hpp
Normal 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
|
||||
15
test/Jamfile
15
test/Jamfile
@@ -50,6 +50,21 @@ 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 ;
|
||||
|
||||
# examples
|
||||
|
||||
obj describe_cxx14 : describe_cxx14.cpp ;
|
||||
explicit describe_cxx14 ;
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ int main() {}
|
||||
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
|
||||
#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1920 && BOOST_MSVC < 1940 && _MSVC_LANG <= 201703L
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is 192x and _MSVC_LANG is 201703L or below")
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC is 192x or 193x and _MSVC_LANG is 201703L or below")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
64
test/descriptor_by_name_test.cpp
Normal file
64
test/descriptor_by_name_test.cpp
Normal 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)
|
||||
65
test/descriptor_by_pointer_test.cpp
Normal file
65
test/descriptor_by_pointer_test.cpp
Normal 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
|
||||
62
test/enum_from_string_test.cpp
Normal file
62
test/enum_from_string_test.cpp
Normal 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)
|
||||
41
test/enum_to_string_test.cpp
Normal file
41
test/enum_to_string_test.cpp
Normal 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)
|
||||
55
test/has_bases_test.cpp
Normal file
55
test/has_bases_test.cpp
Normal 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)
|
||||
58
test/has_enumerators_test.cpp
Normal file
58
test/has_enumerators_test.cpp
Normal 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
55
test/has_members_test.cpp
Normal 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)
|
||||
@@ -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" );
|
||||
|
||||
91
test/operator_eq_test.cpp
Normal file
91
test/operator_eq_test.cpp
Normal 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
99
test/operator_lt_test.cpp
Normal 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)
|
||||
Reference in New Issue
Block a user