Compare commits

...

17 Commits

Author SHA1 Message Date
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
21 changed files with 794 additions and 2233 deletions

View File

@@ -38,15 +38,20 @@ 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
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
install: g++-11
- toolset: clang
compiler: clang++-3.5
cxxstd: "03,11,14"
cxxstd: "03,11"
os: ubuntu-16.04
install: clang-3.5
- toolset: clang
@@ -83,6 +88,7 @@ jobs:
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"
@@ -92,14 +98,24 @@ jobs:
compiler: clang++-8
cxxstd: "03,11,14,17,2a"
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
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15

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,8 +2,8 @@
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
@@ -16,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).

1
doc/.gitignore vendored
View File

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

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
////
@@ -70,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`).
@@ -84,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`.
@@ -97,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

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

@@ -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
@@ -190,8 +198,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 +220,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
@@ -261,8 +271,8 @@ template<class T, unsigned M> using 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

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

@@ -10,6 +10,7 @@
#if !defined(BOOST_DESCRIBE_CXX14)
#define BOOST_DESCRIBE_ENUM(E, ...)
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...)
#else
@@ -60,6 +61,12 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
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, ...) \
@@ -68,6 +75,12 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
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

@@ -129,10 +129,10 @@ 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)
>;
};

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

@@ -25,6 +25,7 @@ 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 ;
@@ -35,7 +36,10 @@ 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 ;
@@ -44,6 +48,8 @@ compile test_d_type.cpp ;
compile-fail enum_struct_fail.cpp ;
compile-fail struct_enum_fail.cpp ;
run class_template_test.cpp ;
obj describe_cxx14 : describe_cxx14.cpp ;
explicit describe_cxx14 ;
@@ -61,3 +67,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)

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)