Coverage Report

Created: 2025-06-13 06:26

/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