mirror of
https://github.com/boostorg/describe.git
synced 2026-01-21 16:52:28 +00:00
Compare commits
15 Commits
feature/de
...
feature/is
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
811003ea0c | ||
|
|
bd8be41591 | ||
|
|
f9477bc177 | ||
|
|
d98f4d1f40 | ||
|
|
2e3b6a6791 | ||
|
|
fabf5c7115 | ||
|
|
ec7aec2b3d | ||
|
|
fc458d48c7 | ||
|
|
6cc4ddafd7 | ||
|
|
ed1175b33a | ||
|
|
d4ebe0943e | ||
|
|
1fa144623d | ||
|
|
5032f55ac1 | ||
|
|
71bfb07be2 | ||
|
|
fc15f03c34 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -148,6 +148,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.0
|
||||
cxxstd: "14"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.1
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
|
||||
@@ -161,6 +161,18 @@ using boost::describe::operators::operator==;
|
||||
The rest of the relational operators are also provided and can
|
||||
be enabled similarly.
|
||||
|
||||
[#example_struct_to_tuple]
|
||||
## struct_to_tuple
|
||||
|
||||
This example defines a function `struct_to_tuple` that takes
|
||||
a described class type as an argument and returns a tuple of
|
||||
all its public members.
|
||||
|
||||
[source]
|
||||
----
|
||||
include::../../example/struct_to_tuple.cpp[lines=5..-1]
|
||||
----
|
||||
|
||||
[#example_to_json]
|
||||
## Automatic Conversion to JSON
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ enum class E: Base { v1, v2, ..., vN };
|
||||
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
|
||||
```
|
||||
|
||||
## <boost/describe/enumerators.hpp>
|
||||
## <boost/describe/{zwsp}enumerators{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -332,7 +332,7 @@ Since the library does not provide a way to describe bases and members separatel
|
||||
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
|
||||
are provided separately for consistency.
|
||||
|
||||
## <boost/describe/enum_to_string.hpp>
|
||||
## <boost/describe/{zwsp}enum_to_string{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -349,7 +349,7 @@ The function `enum_to_string` returns the name of the enumerator `e`. `E` must
|
||||
be a described enumeration type. If `e` does not correspond to one of the described
|
||||
values, the function returns `def`.
|
||||
|
||||
## <boost/describe/enum_from_string.hpp>
|
||||
## <boost/describe/{zwsp}enum_from_string{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -440,7 +440,7 @@ Returns the negated result of `operator<`.
|
||||
Outputs a representation of `t` to `os` by recursively using `operator<<`
|
||||
to output all bases and then all members.
|
||||
|
||||
## <boost/describe/descriptor_by_name.hpp>
|
||||
## <boost/describe/{zwsp}descriptor_by_name{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
@@ -478,7 +478,7 @@ using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
|
||||
using D = descriptor_by_name<L, N>; // descriptor for SomeType::some_member
|
||||
```
|
||||
|
||||
## <boost/describe/descriptor_by_pointer.hpp>
|
||||
## <boost/describe/{zwsp}descriptor_by_pointer{zwsp}.hpp>
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace app
|
||||
{
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
bool operator==( T const& t1, T const& t2 )
|
||||
{
|
||||
bool r = true;
|
||||
|
||||
@@ -19,7 +19,7 @@ template<class T,
|
||||
class D1 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
|
||||
|
||||
T tag_invoke( boost::json::value_to_tag<T> const&, boost::json::value const& v )
|
||||
{
|
||||
|
||||
@@ -15,7 +15,8 @@ namespace app
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
std::size_t hash_value( T const & t )
|
||||
{
|
||||
std::size_t r = 0;
|
||||
|
||||
@@ -10,7 +10,8 @@ using namespace boost::describe;
|
||||
|
||||
template<class T,
|
||||
class Bd = describe_bases<T, mod_any_access>,
|
||||
class Md = describe_members<T, mod_any_access>>
|
||||
class Md = describe_members<T, mod_any_access>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
std::ostream& operator<<( std::ostream & os, T const & t )
|
||||
{
|
||||
os << "{";
|
||||
|
||||
@@ -24,8 +24,8 @@ template<class Archive, class T,
|
||||
class D3 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D4 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<
|
||||
boost::mp11::mp_empty<D2>::value && boost::mp11::mp_empty<D4>::value> >
|
||||
class En = std::enable_if_t< boost::mp11::mp_empty<D2>::value &&
|
||||
boost::mp11::mp_empty<D4>::value && !std::is_union<T>::value> >
|
||||
|
||||
void serialize( Archive & ar, T & t, boost::serialization::version_type )
|
||||
{
|
||||
|
||||
57
example/struct_to_tuple.cpp
Normal file
57
example/struct_to_tuple.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
#include <tuple>
|
||||
|
||||
namespace desc = boost::describe;
|
||||
|
||||
template<class T, template<class...> class L, class... D>
|
||||
auto struct_to_tuple_impl( T const& t, L<D...> )
|
||||
{
|
||||
return std::make_tuple( t.*D::pointer... );
|
||||
}
|
||||
|
||||
template<class T,
|
||||
class Dm = desc::describe_members<T,
|
||||
desc::mod_public | desc::mod_inherited>,
|
||||
class En = std::enable_if_t<!std::is_union<T>::value> >
|
||||
auto struct_to_tuple( T const& t )
|
||||
{
|
||||
return struct_to_tuple_impl( t, Dm() );
|
||||
}
|
||||
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct X
|
||||
{
|
||||
int a = 1;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), (a))
|
||||
|
||||
struct Y
|
||||
{
|
||||
float b = 3.14f;
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y, (), (b))
|
||||
|
||||
struct Z: X, Y
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Z, (X, Y), ())
|
||||
|
||||
int main()
|
||||
{
|
||||
Z z;
|
||||
|
||||
auto tp = struct_to_tuple( z );
|
||||
|
||||
std::cout <<
|
||||
boost::core::type_name<decltype(tp)>() << ": "
|
||||
<< std::get<0>(tp) << ", " << std::get<1>(tp);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ template<class T,
|
||||
class D1 = boost::describe::describe_members<T,
|
||||
boost::describe::mod_public | boost::describe::mod_protected>,
|
||||
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
|
||||
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value && !std::is_union<T>::value> >
|
||||
|
||||
void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, T const & t )
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace describe
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> using _describe_bases = decltype( boost_base_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_bases = decltype( boost_base_descriptor_fn( static_cast<T**>(0) ) );
|
||||
|
||||
template<unsigned M> struct base_filter
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace describe
|
||||
friend BOOST_DESCRIBE_PRIVATE_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
|
||||
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
|
||||
static_assert(std::is_class<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_BASES(C, BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_PUBLIC_MEMBERS(C, BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_PROTECTED_MEMBERS(C) \
|
||||
@@ -54,17 +54,17 @@ namespace describe
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS_(...) BOOST_DESCRIBE_PRIVATE_MEMBERS(__VA_ARGS__)
|
||||
|
||||
#define BOOST_DESCRIBE_CLASS(C, Bases, Public, Protected, Private) \
|
||||
friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
|
||||
friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
|
||||
friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Public) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PROTECTED_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Protected) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_PRIVATE_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Private)
|
||||
|
||||
#define BOOST_DESCRIBE_STRUCT(C, Bases, Members) \
|
||||
static_assert(std::is_class<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
|
||||
BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
|
||||
static_assert(std::is_class<C>::value || std::is_union<C>::value, "BOOST_DESCRIBE_STRUCT should only be used with class types"); \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_BASES_(C BOOST_DESCRIBE_PP_UNPACK Bases) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PUBLIC_MEMBERS_(C BOOST_DESCRIBE_PP_UNPACK Members) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PROTECTED_MEMBERS_(C) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED BOOST_DESCRIBE_PRIVATE_MEMBERS_(C)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,12 +37,12 @@ template<class... T> auto base_descriptor_fn_impl( int, T... )
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_BASES(C, ...) inline auto boost_base_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::base_descriptor_fn_impl( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_BASE_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,4 +27,12 @@
|
||||
# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST const
|
||||
#endif
|
||||
|
||||
#define BOOST_DESCRIBE_MAYBE_UNUSED
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(maybe_unused)
|
||||
# undef BOOST_DESCRIBE_MAYBE_UNUSED
|
||||
# define BOOST_DESCRIBE_MAYBE_UNUSED [[maybe_unused]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED
|
||||
|
||||
@@ -53,24 +53,24 @@ template<class C, class F> constexpr auto mfn( F * p ) { return p; }
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, __VA_ARGS__) ); }
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PUBLIC_MEMBERS(C, ...) inline auto boost_public_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_public>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PROTECTED_MEMBERS(C, ...) inline auto boost_protected_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_protected>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C * ) \
|
||||
#define BOOST_DESCRIBE_PRIVATE_MEMBERS(C, ...) inline auto boost_private_member_descriptor_fn( C** ) \
|
||||
{ return boost::describe::detail::member_descriptor_fn_impl<boost::describe::mod_private>( 0 BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_MEMBER_IMPL, C, ##__VA_ARGS__) ); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
|
||||
}
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
inline auto boost_enum_descriptor_fn( E* ) \
|
||||
inline auto boost_enum_descriptor_fn( E** ) \
|
||||
{ return boost::describe::detail::enum_descriptor_fn_impl( 0
|
||||
|
||||
#define BOOST_DESCRIBE_ENUM_ENTRY(E, e) , []{ struct _boost_desc { \
|
||||
@@ -71,13 +71,13 @@ template<class... T> auto enum_descriptor_fn_impl( int, T... )
|
||||
|
||||
#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_MAYBE_UNUSED BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
|
||||
BOOST_DESCRIBE_ENUM_END(E)
|
||||
|
||||
#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) \
|
||||
static_assert(std::is_enum<E>::value, "BOOST_DESCRIBE_NESTED_ENUM should only be used with enums"); \
|
||||
friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_MAYBE_UNUSED friend BOOST_DESCRIBE_ENUM_BEGIN(E) \
|
||||
BOOST_DESCRIBE_PP_FOR_EACH(BOOST_DESCRIBE_ENUM_ENTRY, E, ##__VA_ARGS__) \
|
||||
BOOST_DESCRIBE_ENUM_END(E)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace describe
|
||||
|
||||
// describe_enumerators<E>
|
||||
|
||||
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E*>(0) ) );
|
||||
template<class E> using describe_enumerators = decltype( boost_enum_descriptor_fn( static_cast<E**>(0) ) );
|
||||
|
||||
// has_describe_enumerators<E>
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace detail
|
||||
|
||||
// _describe_members<T>
|
||||
|
||||
template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T*>(0) ) );
|
||||
template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T**>(0) ) );
|
||||
|
||||
template<class T> using _describe_members = mp11::mp_append<_describe_public_members<T>, _describe_protected_members<T>, _describe_private_members<T>>;
|
||||
|
||||
|
||||
@@ -109,49 +109,49 @@ namespace operators
|
||||
{
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator==( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::eq( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator!=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::eq( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator<( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::lt( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator>=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::lt( t1, t2 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator>( T const& t1, T const& t2 )
|
||||
{
|
||||
return detail::lt( t2, t1 );
|
||||
}
|
||||
|
||||
template<class T> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value, bool>
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
|
||||
operator<=( T const& t1, T const& t2 )
|
||||
{
|
||||
return !detail::lt( t2, t1 );
|
||||
}
|
||||
|
||||
template<class T, class Ch, class Tr> std::enable_if_t<
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value,
|
||||
has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
|
||||
std::basic_ostream<Ch, Tr>&>
|
||||
operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"description": "A C++14 reflection library.",
|
||||
"category": [
|
||||
"Emulation",
|
||||
"Metaprogramming"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -63,6 +63,12 @@ run operator_lt_test.cpp ;
|
||||
run descriptor_by_name_test.cpp ;
|
||||
run descriptor_by_pointer_test.cpp ;
|
||||
|
||||
compile unnamed_namespace_test.cpp ;
|
||||
compile unnamed_namespace_test2.cpp ;
|
||||
|
||||
run union_test.cpp ;
|
||||
run union_test2.cpp ;
|
||||
|
||||
# examples
|
||||
|
||||
obj describe_cxx14 : describe_cxx14.cpp ;
|
||||
@@ -85,3 +91,4 @@ run ../example/json_rpc.cpp : : : $(CXX14) $(JSON) ;
|
||||
run ../example/hash_value.cpp : : : $(CXX14) ;
|
||||
run ../example/equality.cpp : : : $(CXX14) ;
|
||||
link ../example/console.cpp : $(CXX14) $(JSON) ;
|
||||
run ../example/struct_to_tuple.cpp : : : $(CXX14) ;
|
||||
|
||||
@@ -27,6 +27,9 @@ struct X3 {};
|
||||
class X4 {};
|
||||
union X5 {};
|
||||
|
||||
struct X6: X1 {};
|
||||
struct X7: X2 {};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::describe::has_describe_bases;
|
||||
@@ -46,6 +49,8 @@ int main()
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X3>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X4>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X5>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X6>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<X7>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_bases<void>));
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ struct X3 {};
|
||||
class X4 {};
|
||||
union X5 {};
|
||||
|
||||
struct X6: X1 {};
|
||||
struct X7: X2 {};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::describe::has_describe_members;
|
||||
@@ -46,6 +49,8 @@ int main()
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X3>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X4>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X5>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X6>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<X7>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((has_describe_members<void>));
|
||||
|
||||
|
||||
79
test/union_test.cpp
Normal file
79
test/union_test.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2020, 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/members.hpp>
|
||||
#include <boost/describe/class.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX11)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
|
||||
int main() {}
|
||||
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
union A
|
||||
{
|
||||
int m1;
|
||||
static int m2;
|
||||
int f1() const { return m1; }
|
||||
static int f2() { return m2; }
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(A, (), (m1, m2, f1, f2))
|
||||
|
||||
int A::m2;
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe;
|
||||
using namespace boost::mp11;
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_any_access | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m1 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_public );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m2 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f1 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f2 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX11)
|
||||
153
test/union_test2.cpp
Normal file
153
test/union_test2.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright 2020, 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe/members.hpp>
|
||||
#include <boost/describe/class.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX11)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++11 is not available")
|
||||
int main() {}
|
||||
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because g++ 4.8")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
union A
|
||||
{
|
||||
public:
|
||||
|
||||
int m1;
|
||||
static int m2;
|
||||
int f1() const { return m1; }
|
||||
static int f2() { return m2; }
|
||||
|
||||
protected:
|
||||
|
||||
int m3;
|
||||
static int m4;
|
||||
int f3() const { return m3; }
|
||||
static int f4() { return m4; }
|
||||
|
||||
private:
|
||||
|
||||
int m5;
|
||||
static int m6;
|
||||
int f5() const { return m5; }
|
||||
static int f6() { return m6; }
|
||||
|
||||
BOOST_DESCRIBE_CLASS(A, (), (m1, m2, f1, f2), (m3, m4, f3, f4), (m5, m6, f5, f6))
|
||||
|
||||
friend int main();
|
||||
};
|
||||
|
||||
int A::m2;
|
||||
int A::m4;
|
||||
int A::m6;
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe;
|
||||
using namespace boost::mp11;
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_public | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m1 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m1" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_public );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m2 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m2" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_public | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f1 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f1" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_public | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f2 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f2" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_public | mod_static | mod_function );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_protected | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m3 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m3" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_protected );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m4 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m4" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_protected | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f3 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f3" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_protected | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f4 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f4" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_protected | mod_static | mod_function );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_members<A, mod_private | mod_any_member>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
|
||||
using D1 = mp_at_c<L, 0>;
|
||||
using D2 = mp_at_c<L, 1>;
|
||||
using D3 = mp_at_c<L, 2>;
|
||||
using D4 = mp_at_c<L, 3>;
|
||||
|
||||
BOOST_TEST( D1::pointer == &A::m5 );
|
||||
BOOST_TEST_CSTR_EQ( D1::name, "m5" );
|
||||
BOOST_TEST_EQ( D1::modifiers, mod_private );
|
||||
|
||||
BOOST_TEST( D2::pointer == &A::m6 );
|
||||
BOOST_TEST_CSTR_EQ( D2::name, "m6" );
|
||||
BOOST_TEST_EQ( D2::modifiers, mod_private | mod_static );
|
||||
|
||||
BOOST_TEST( D3::pointer == &A::f5 );
|
||||
BOOST_TEST_CSTR_EQ( D3::name, "f5" );
|
||||
BOOST_TEST_EQ( D3::modifiers, mod_private | mod_function );
|
||||
|
||||
BOOST_TEST( D4::pointer == &A::f6 );
|
||||
BOOST_TEST_CSTR_EQ( D4::name, "f6" );
|
||||
BOOST_TEST_EQ( D4::modifiers, mod_private | mod_static | mod_function );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX11)
|
||||
35
test/unnamed_namespace_test.cpp
Normal file
35
test/unnamed_namespace_test.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum E { v };
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E, v)
|
||||
|
||||
struct S
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(S, (), ())
|
||||
|
||||
class C
|
||||
{
|
||||
BOOST_DESCRIBE_CLASS(C, (), (), (), ())
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
45
test/unnamed_namespace_test2.cpp
Normal file
45
test/unnamed_namespace_test2.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2021 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/describe.hpp>
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
enum E { v };
|
||||
|
||||
BOOST_DESCRIBE_ENUM(E, v)
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(X, (), ())
|
||||
|
||||
class Y
|
||||
{
|
||||
BOOST_DESCRIBE_CLASS(Y, (), (), (), ())
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace boost::describe;
|
||||
|
||||
using L1 = describe_enumerators<E>;
|
||||
|
||||
using L2 = describe_bases<X, mod_any_access>;
|
||||
using L3 = describe_members<X, mod_any_access>;
|
||||
|
||||
using L4 = describe_bases<Y, mod_any_access>;
|
||||
using L5 = describe_members<Y, mod_any_access>;
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
Reference in New Issue
Block a user