mirror of
https://github.com/boostorg/describe.git
synced 2026-02-02 08:42:16 +00:00
Compare commits
4 Commits
feature/tr
...
feature/mo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe26439f39 | ||
|
|
a876e619b7 | ||
|
|
19bb4254bc | ||
|
|
109bb07163 |
@@ -5,7 +5,7 @@
|
||||
// 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/compute_base_modifiers.hpp>
|
||||
#include <boost/describe/detail/pp_for_each.hpp>
|
||||
#include <boost/describe/detail/list.hpp>
|
||||
#include <type_traits>
|
||||
@@ -17,29 +17,13 @@ namespace describe
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// is_public_base_of
|
||||
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
|
||||
|
||||
// is_virtual_base_of
|
||||
template<class T, class U, class = void> struct can_cast: std::false_type {};
|
||||
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
|
||||
|
||||
template<class T, class U> using is_virtual_base_of =
|
||||
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
|
||||
|
||||
// base_modifiers
|
||||
template<class C, class B> constexpr unsigned base_modifiers() noexcept
|
||||
{
|
||||
return (is_public_base_of<B, C>::value? mod_public: mod_private) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
|
||||
}
|
||||
|
||||
// base_descriptor
|
||||
template<class C, class B> struct base_descriptor
|
||||
{
|
||||
static_assert( std::is_base_of<B, C>::value, "A type listed as a base is not one" );
|
||||
|
||||
using type = B;
|
||||
static constexpr unsigned modifiers = base_modifiers<C, B>();
|
||||
static constexpr unsigned modifiers = compute_base_modifiers<C, B>();
|
||||
};
|
||||
|
||||
template<class C, class B> constexpr unsigned base_descriptor<C, B>::modifiers;
|
||||
|
||||
73
include/boost/describe/detail/compute_base_modifiers.hpp
Normal file
73
include/boost/describe/detail/compute_base_modifiers.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
|
||||
#define BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_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/modifiers.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace describe
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4594) // can never be instantiated - indirect virtual base class is inaccessible
|
||||
# pragma warning(disable: 4624) // destructor was implicitly defined as deleted
|
||||
#endif
|
||||
|
||||
// is_public_base_of
|
||||
|
||||
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
|
||||
|
||||
// is_protected_base_of
|
||||
|
||||
struct ipb_final
|
||||
{
|
||||
template<class T, class U> using fn = std::false_type;
|
||||
};
|
||||
|
||||
struct ipb_non_final
|
||||
{
|
||||
template<class T, class U> struct fn: U
|
||||
{
|
||||
static std::true_type f( T* );
|
||||
|
||||
template<class X> static auto g( X x ) -> decltype( f(x) );
|
||||
static std::false_type g( ... );
|
||||
|
||||
using type = decltype( g((U*)0) );
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class U> using is_protected_base_of =
|
||||
typename std::conditional<std::is_final<U>::value || std::is_union<U>::value, ipb_final, ipb_non_final>::type::template fn<T, U>::type;
|
||||
|
||||
// is_virtual_base_of
|
||||
|
||||
template<class T, class U, class = void> struct can_cast: std::false_type {};
|
||||
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
|
||||
|
||||
template<class T, class U> using is_virtual_base_of =
|
||||
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
|
||||
|
||||
// compute_base_modifiers
|
||||
template<class C, class B> constexpr unsigned compute_base_modifiers() noexcept
|
||||
{
|
||||
return (is_public_base_of<B, C>::value? mod_public: (is_protected_base_of<B, C>::value? mod_protected: mod_private)) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace describe
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
|
||||
@@ -17,7 +17,10 @@ run quick.cpp ;
|
||||
run pp_for_each_test.cpp ;
|
||||
|
||||
run enumerators_test.cpp ;
|
||||
|
||||
run compute_base_modifiers.cpp ;
|
||||
run bases_test.cpp ;
|
||||
|
||||
run members_test.cpp ;
|
||||
run members_test2.cpp ;
|
||||
run members_test3.cpp ;
|
||||
|
||||
@@ -25,15 +25,26 @@ struct X3
|
||||
{
|
||||
};
|
||||
|
||||
struct X4
|
||||
struct V1
|
||||
{
|
||||
V1(int);
|
||||
};
|
||||
|
||||
struct V2
|
||||
{
|
||||
V2(int);
|
||||
};
|
||||
|
||||
struct V3
|
||||
{
|
||||
V3(int);
|
||||
};
|
||||
|
||||
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
|
||||
{
|
||||
};
|
||||
|
||||
struct Y: public X1, private X2, public virtual X3, private virtual X4
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, X4), ())
|
||||
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, V1, V2, V3), ())
|
||||
|
||||
#if !defined(BOOST_DESCRIBE_CXX14)
|
||||
|
||||
@@ -57,22 +68,46 @@ int main()
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 0 );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<X, mod_public>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 0 );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<X, mod_protected>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 0 );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<X, mod_private>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 0 );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<Y, mod_any_access>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 4 );
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 6 );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X2 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 2>::type, X3 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_public | mod_virtual );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_private );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, X4 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_private | mod_virtual );
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, V1 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_public | mod_virtual );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 4>::type, V2 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 4>::modifiers), mod_protected | mod_virtual );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 5>::type, V3 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 5>::modifiers), mod_private | mod_virtual );
|
||||
}
|
||||
|
||||
{
|
||||
@@ -83,28 +118,34 @@ int main()
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X3 );
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V1 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_public | mod_virtual );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<Y, mod_protected>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 2 );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_protected );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V2 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected | mod_virtual );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<Y, mod_private>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 2 );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X3 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_private );
|
||||
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X4 );
|
||||
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V3 );
|
||||
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private | mod_virtual );
|
||||
}
|
||||
|
||||
{
|
||||
using L = describe_bases<Y, mod_protected>;
|
||||
|
||||
BOOST_TEST_EQ( mp_size<L>::value, 0 );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
119
test/compute_base_modifiers.cpp
Normal file
119
test/compute_base_modifiers.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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_CXX14)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/describe/detail/compute_base_modifiers.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
struct X1
|
||||
{
|
||||
};
|
||||
|
||||
struct X2
|
||||
{
|
||||
};
|
||||
|
||||
struct X3
|
||||
{
|
||||
};
|
||||
|
||||
struct V1
|
||||
{
|
||||
V1(int);
|
||||
};
|
||||
|
||||
struct V2
|
||||
{
|
||||
V2(int);
|
||||
};
|
||||
|
||||
struct V3
|
||||
{
|
||||
V3(int);
|
||||
};
|
||||
|
||||
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
|
||||
{
|
||||
};
|
||||
|
||||
struct Z final: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::describe::detail;
|
||||
using namespace boost::describe;
|
||||
|
||||
BOOST_TEST( (is_public_base_of<X1, Y>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X1, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, X1>()), mod_public );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<X2, Y>::value) );
|
||||
BOOST_TEST( (is_protected_base_of<X2, Y>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X2, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, X2>()), mod_protected );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<X3, Y>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<X3, Y>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X3, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, X3>()), mod_private );
|
||||
|
||||
BOOST_TEST( (is_public_base_of<V1, Y>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V1, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, V1>()), mod_public | mod_virtual );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<V2, Y>::value) );
|
||||
BOOST_TEST( (is_protected_base_of<V2, Y>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V2, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, V2>()), mod_protected | mod_virtual );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<V3, Y>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<V3, Y>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V3, Y>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Y, V3>()), mod_private | mod_virtual );
|
||||
|
||||
BOOST_TEST( (is_public_base_of<X1, Z>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X1, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, X1>()), mod_public );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<X2, Z>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<X2, Z>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X2, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, X2>()), mod_private );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<X3, Z>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<X3, Z>::value) );
|
||||
BOOST_TEST( (!is_virtual_base_of<X3, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, X3>()), mod_private );
|
||||
|
||||
BOOST_TEST( (is_public_base_of<V1, Z>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V1, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, V1>()), mod_public | mod_virtual );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<V2, Z>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<V2, Z>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V2, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, V2>()), mod_private | mod_virtual );
|
||||
|
||||
BOOST_TEST( (!is_public_base_of<V3, Z>::value) );
|
||||
BOOST_TEST( (!is_protected_base_of<V3, Z>::value) );
|
||||
BOOST_TEST( (is_virtual_base_of<V3, Z>::value) );
|
||||
BOOST_TEST_EQ( (compute_base_modifiers<Z, V3>()), mod_private | mod_virtual );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_DESCRIBE_CXX14)
|
||||
Reference in New Issue
Block a user