/src/boost/boost/describe/members.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED |
2 | | #define BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED |
3 | | |
4 | | // Copyright 2020 Peter Dimov |
5 | | // Distributed under the Boost Software License, Version 1.0. |
6 | | // https://www.boost.org/LICENSE_1_0.txt |
7 | | |
8 | | #include <boost/describe/modifiers.hpp> |
9 | | #include <boost/describe/bases.hpp> |
10 | | #include <boost/describe/detail/void_t.hpp> |
11 | | #include <boost/describe/detail/cx_streq.hpp> |
12 | | #include <boost/describe/detail/config.hpp> |
13 | | |
14 | | #if defined(BOOST_DESCRIBE_CXX11) |
15 | | |
16 | | #include <boost/mp11/algorithm.hpp> |
17 | | #include <boost/mp11/utility.hpp> |
18 | | #include <boost/mp11/integral.hpp> |
19 | | #include <boost/mp11/list.hpp> |
20 | | #include <boost/mp11/bind.hpp> |
21 | | #include <type_traits> |
22 | | |
23 | | namespace boost |
24 | | { |
25 | | namespace describe |
26 | | { |
27 | | namespace detail |
28 | | { |
29 | | |
30 | | // _describe_members<T> |
31 | | |
32 | | template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T**>(0) ) ); |
33 | | template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T**>(0) ) ); |
34 | | template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T**>(0) ) ); |
35 | | |
36 | | template<class T> using _describe_members = mp11::mp_append<_describe_public_members<T>, _describe_protected_members<T>, _describe_private_members<T>>; |
37 | | |
38 | | // describe_inherited_members<T> |
39 | | |
40 | | // T: type |
41 | | // V: list of virtual bases visited so far |
42 | | template<class T, class V> struct describe_inherited_members_impl; |
43 | | template<class T, class V> using describe_inherited_members = typename describe_inherited_members_impl<T, V>::type; |
44 | | |
45 | | // L: list of base class descriptors |
46 | | // T: derived type |
47 | | // V: list of virtual bases visited so far |
48 | | template<class L, class T, class V> struct describe_inherited_members2_impl; |
49 | | template<class L, class T, class V> using describe_inherited_members2 = typename describe_inherited_members2_impl<L, T, V>::type; |
50 | | |
51 | | template<class T, class V> struct describe_inherited_members_impl |
52 | | { |
53 | | using R1 = describe_inherited_members2<describe_bases<T, mod_any_access>, T, V>; |
54 | | using R2 = _describe_members<T>; |
55 | | |
56 | | using type = mp11::mp_append<R1, R2>; |
57 | | }; |
58 | | |
59 | | template<template<class...> class L, class T, class V> struct describe_inherited_members2_impl<L<>, T, V> |
60 | | { |
61 | | using type = L<>; |
62 | | }; |
63 | | |
64 | | template<class D1, class D2> using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >; |
65 | | |
66 | | template<class D, class L> using name_is_hidden = mp11::mp_any_of_q<L, mp11::mp_bind_front<name_matches, D>>; |
67 | | |
68 | | constexpr unsigned cx_max( unsigned m1, unsigned m2 ) |
69 | 0 | { |
70 | 0 | return m1 > m2? m1: m2; |
71 | 0 | } |
72 | | |
73 | | template<class T, unsigned Bm> struct update_modifiers |
74 | | { |
75 | | template<class D> struct fn |
76 | | { |
77 | | using L = _describe_members<T>; |
78 | | static constexpr unsigned hidden = name_is_hidden<D, L>::value? mod_hidden: 0; |
79 | | |
80 | | static constexpr unsigned mods = D::modifiers; |
81 | | static constexpr unsigned access = cx_max( mods & mod_any_access, Bm & mod_any_access ); |
82 | | |
83 | | static constexpr decltype(D::pointer) pointer = D::pointer; |
84 | | static constexpr decltype(D::name) name = D::name; |
85 | | static constexpr unsigned modifiers = ( mods & ~mod_any_access ) | access | mod_inherited | hidden; |
86 | | }; |
87 | | }; |
88 | | |
89 | | #ifndef __cpp_inline_variables |
90 | | template<class T, unsigned Bm> template<class D> constexpr decltype(D::pointer) update_modifiers<T, Bm>::fn<D>::pointer; |
91 | | template<class T, unsigned Bm> template<class D> constexpr decltype(D::name) update_modifiers<T, Bm>::fn<D>::name; |
92 | | template<class T, unsigned Bm> template<class D> constexpr unsigned update_modifiers<T, Bm>::fn<D>::modifiers; |
93 | | #endif |
94 | | |
95 | | template<class D> struct gather_virtual_bases_impl; |
96 | | template<class D> using gather_virtual_bases = typename gather_virtual_bases_impl<D>::type; |
97 | | |
98 | | template<class D> struct gather_virtual_bases_impl |
99 | | { |
100 | | using B = typename D::type; |
101 | | static constexpr unsigned M = D::modifiers; |
102 | | |
103 | | using R1 = mp11::mp_transform<gather_virtual_bases, describe_bases<B, mod_any_access>>; |
104 | | using R2 = mp11::mp_apply<mp11::mp_append, R1>; |
105 | | |
106 | | using type = mp11::mp_if_c<(M & mod_virtual) != 0, mp11::mp_push_front<R2, B>, R2>; |
107 | | }; |
108 | | |
109 | | template<template<class...> class L, class D1, class... D, class T, class V> struct describe_inherited_members2_impl<L<D1, D...>, T, V> |
110 | | { |
111 | | using B = typename D1::type; |
112 | | static constexpr unsigned M = D1::modifiers; |
113 | | |
114 | | using R1 = mp11::mp_if_c<(M & mod_virtual) && mp11::mp_contains<V, B>::value, L<>, describe_inherited_members<B, V>>; |
115 | | |
116 | | using R2 = mp11::mp_transform_q<update_modifiers<T, M>, R1>; |
117 | | |
118 | | using V2 = mp11::mp_append<V, gather_virtual_bases<D1>>; |
119 | | using R3 = describe_inherited_members2<L<D...>, T, V2>; |
120 | | |
121 | | using type = mp11::mp_append<R2, R3>; |
122 | | }; |
123 | | |
124 | | // describe_members<T, M> |
125 | | |
126 | | template<class T, unsigned M> using describe_members = mp11::mp_eval_if_c<(M & mod_inherited) == 0, _describe_members<T>, describe_inherited_members, T, mp11::mp_list<>>; |
127 | | |
128 | | // member_filter |
129 | | |
130 | | template<unsigned M> struct member_filter |
131 | | { |
132 | | template<class T> using fn = mp11::mp_bool< |
133 | | (M & mod_any_access & T::modifiers) != 0 && |
134 | | ( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) && |
135 | | ( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) && |
136 | | (M & mod_hidden) >= (T::modifiers & mod_hidden) |
137 | | >; |
138 | | }; |
139 | | |
140 | | // has_describe_members |
141 | | |
142 | | template<class T, class En = void> struct has_describe_members: std::false_type |
143 | | { |
144 | | }; |
145 | | |
146 | | template<class T> struct has_describe_members<T, void_t<_describe_members<T>>>: std::true_type |
147 | | { |
148 | | }; |
149 | | |
150 | | } // namespace detail |
151 | | |
152 | | template<class T, unsigned M> using describe_members = mp11::mp_copy_if_q<detail::describe_members<T, M>, detail::member_filter<M>>; |
153 | | |
154 | | template<class T> using has_describe_members = detail::has_describe_members<T>; |
155 | | |
156 | | } // namespace describe |
157 | | } // namespace boost |
158 | | |
159 | | #endif // !defined(BOOST_DESCRIBE_CXX11) |
160 | | |
161 | | #endif // #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED |