#ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED #define BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED // Copyright 2020 Peter Dimov // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #if defined(BOOST_DESCRIBE_CXX11) #include #include #include #include #include #include namespace boost { namespace describe { namespace detail { // _describe_members template using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast(0) ) ); template using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast(0) ) ); template using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast(0) ) ); template using _describe_members = mp11::mp_append<_describe_public_members, _describe_protected_members, _describe_private_members>; // describe_inherited_members // T: type // V: list of virtual bases visited so far template struct describe_inherited_members_impl; template using describe_inherited_members = typename describe_inherited_members_impl::type; // L: list of base class descriptors // T: derived type // V: list of virtual bases visited so far template struct describe_inherited_members2_impl; template using describe_inherited_members2 = typename describe_inherited_members2_impl::type; template struct describe_inherited_members_impl { using R1 = describe_inherited_members2, T, V>; using R2 = _describe_members; using type = mp11::mp_append; }; template class L, class T, class V> struct describe_inherited_members2_impl, T, V> { using type = L<>; }; template using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >; template using name_is_hidden = mp11::mp_any_of_q>; constexpr unsigned cx_max( unsigned m1, unsigned m2 ) { return m1 > m2? m1: m2; } template struct update_modifiers { template struct fn { using L = _describe_members; static constexpr unsigned hidden = name_is_hidden::value? mod_hidden: 0; static constexpr unsigned mods = D::modifiers; static constexpr unsigned access = cx_max( mods & mod_any_access, Bm & mod_any_access ); static constexpr decltype(D::pointer) pointer = D::pointer; static constexpr decltype(D::name) name = D::name; static constexpr unsigned modifiers = ( mods & ~mod_any_access ) | access | mod_inherited | hidden; }; }; template template constexpr decltype(D::pointer) update_modifiers::fn::pointer; template template constexpr decltype(D::name) update_modifiers::fn::name; template template constexpr unsigned update_modifiers::fn::modifiers; template struct gather_virtual_bases_impl; template using gather_virtual_bases = typename gather_virtual_bases_impl::type; template struct gather_virtual_bases_impl { using B = typename D::type; static constexpr unsigned M = D::modifiers; using R1 = mp11::mp_transform>; using R2 = mp11::mp_apply; using type = mp11::mp_if_c<(M & mod_virtual) != 0, mp11::mp_push_front, R2>; }; template class L, class D1, class... D, class T, class V> struct describe_inherited_members2_impl, T, V> { using B = typename D1::type; static constexpr unsigned M = D1::modifiers; using R1 = mp11::mp_if_c<(M & mod_virtual) && mp11::mp_contains::value, L<>, describe_inherited_members>; using R2 = mp11::mp_transform_q, R1>; using V2 = mp11::mp_append>; using R3 = describe_inherited_members2, T, V2>; using type = mp11::mp_append; }; // describe_members template using describe_members = mp11::mp_eval_if_c<(M & mod_inherited) == 0, _describe_members, describe_inherited_members, T, mp11::mp_list<>>; // member_filter template struct member_filter { template using fn = mp11::mp_bool< (M & mod_any_access & T::modifiers) != 0 && ( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) && ( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) && (M & mod_hidden) >= (T::modifiers & mod_hidden) >; }; // has_describe_members template struct has_describe_members: std::false_type { }; template struct has_describe_members>>: std::true_type { }; } // namespace detail template using describe_members = mp11::mp_copy_if_q, detail::member_filter>; template using has_describe_members = detail::has_describe_members; } // namespace describe } // namespace boost #endif // !defined(BOOST_DESCRIBE_CXX11) #endif // #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED