welder
0.1.0
Bindings for annotated C++ types, from C++26 reflection
Toggle main menu visibility
Loading...
Searching...
No Matches
virtuals.hpp
Go to the documentation of this file.
1
#pragma once
2
#include <cstddef>
3
#include <meta>
4
#include <string_view>
5
#include <vector>
6
7
#include <
welder/diag.hpp
>
// no_matching_virtual_slot
8
29
30
namespace
welder::inline v0 {
31
32
// --- bind_flat: opt out of trampoline support for a virtual type -------------
33
41
struct
bind_flat_spec
{};
42
58
inline
constexpr
bind_flat_spec
bind_flat
{};
59
63
consteval
bool
bound_flat
(std::meta::info entity) {
64
return
!std::meta::annotations_of_with_type(entity, ^^
bind_flat_spec
).empty();
65
}
66
67
// --- virtual-method reflection ----------------------------------------------
68
78
consteval
bool
is_overridable_virtual
(std::meta::info member) {
79
return
std::meta::is_function(member) && std::meta::is_virtual(member) &&
80
!std::meta::is_destructor(member) && !
bound_flat
(member);
81
}
82
83
namespace
detail {
84
94
consteval
bool
same_slot
(std::meta::info a, std::meta::info b) {
95
if
(std::meta::identifier_of(a) != std::meta::identifier_of(b))
96
return
false
;
97
if
(std::meta::is_const(a) != std::meta::is_const(b) ||
98
std::meta::is_volatile(a) != std::meta::is_volatile(b) ||
99
std::meta::is_lvalue_reference_qualified(a) !=
100
std::meta::is_lvalue_reference_qualified(b) ||
101
std::meta::is_rvalue_reference_qualified(a) !=
102
std::meta::is_rvalue_reference_qualified(b))
103
return
false
;
104
auto
pa{std::meta::parameters_of(a)};
105
auto
pb{std::meta::parameters_of(b)};
106
if
(pa.size() != pb.size())
107
return
false
;
108
for
(std::size_t i{0}; i < pa.size(); ++i)
109
if
(std::meta::type_of(pa[i]) != std::meta::type_of(pb[i]))
110
return
false
;
111
return
true
;
112
}
113
135
consteval
void
collect_virtuals
(std::meta::info type,
136
std::vector<std::meta::info>& slots) {
137
for
(
auto
m :
138
std::meta::members_of(type, std::meta::access_context::unchecked())) {
139
if
(!std::meta::is_function(m) || !std::meta::is_virtual(m) ||
140
std::meta::is_destructor(m) || !std::meta::has_identifier(m))
141
continue
;
142
bool
seen{
false
};
143
for
(
auto
s : slots)
144
if
(
same_slot
(s, m)) {
145
seen =
true
;
146
break
;
147
}
148
if
(!seen)
149
slots.push_back(m);
150
}
151
for
(
auto
b :
152
std::meta::bases_of(type, std::meta::access_context::unchecked()))
153
collect_virtuals
(std::meta::dealias(std::meta::type_of(b)), slots);
154
}
155
156
}
// namespace detail
157
174
consteval
std::vector<std::meta::info>
overridable_virtuals
(std::meta::info type) {
175
// Accept an alias reflection too (the spelling a generated trampoline uses for
176
// a class-template specialization): the walk needs the underlying class.
177
type = std::meta::dealias(type);
178
std::vector<std::meta::info> all{};
179
detail::collect_virtuals
(type, all);
180
std::vector<std::meta::info> out{};
181
for
(
auto
s : all)
182
if
(!
bound_flat
(s) && !std::meta::is_private(s))
183
out.push_back(s);
184
return
out;
185
}
186
213
consteval
std::meta::info
virtual_slot
(std::meta::info type, std::string_view name,
214
std::meta::info fn_type) {
215
for
(
auto
s :
overridable_virtuals
(type))
216
if
(std::meta::identifier_of(s) == name &&
217
std::meta::type_of(s) == std::meta::dealias(fn_type))
218
return
s;
219
throw
diag::no_matching_virtual_slot
{};
220
}
221
232
consteval
std::size_t
virtual_slot_count
(std::meta::info type) {
233
return
overridable_virtuals
(type).size();
234
}
235
239
consteval
bool
has_virtual_methods
(std::meta::info type) {
240
return
!
overridable_virtuals
(type).empty();
241
}
242
243
}
// namespace welder::inline v0
diag.hpp
welder's consteval diagnostics, collected in one place: every hand-rolled compile-time error the libr...
welder::detail::collect_virtuals
consteval void collect_virtuals(std::meta::info type, std::vector< std::meta::info > &slots)
Accumulate the most-derived declaration of every virtual member function reachable in type's complete...
Definition
virtuals.hpp:135
welder::detail::same_slot
consteval bool same_slot(std::meta::info a, std::meta::info b)
Do a and b declare the same vtable slot?
Definition
virtuals.hpp:94
welder
Definition
annotations.hpp:18
welder::is_overridable_virtual
consteval bool is_overridable_virtual(std::meta::info member)
Is member an overridable virtual — a virtual member function that welder routes through the trampolin...
Definition
virtuals.hpp:78
welder::bind_flat
constexpr bind_flat_spec bind_flat
Mark a virtual entity as deliberately bound non-overridably.
Definition
virtuals.hpp:58
welder::has_virtual_methods
consteval bool has_virtual_methods(std::meta::info type)
Does type declare or inherit any overridable virtual method?
Definition
virtuals.hpp:239
welder::virtual_slot
consteval std::meta::info virtual_slot(std::meta::info type, std::string_view name, std::meta::info fn_type)
The overridable virtual slot of type named name whose function type is fn_type — the hand-written dis...
Definition
virtuals.hpp:213
welder::virtual_slot_count
consteval std::size_t virtual_slot_count(std::meta::info type)
The number of overridable virtual member functions of type, inherited ones included.
Definition
virtuals.hpp:232
welder::bound_flat
consteval bool bound_flat(std::meta::info entity)
Does entity (a type or a member function) carry a bind_flat mark?
Definition
virtuals.hpp:63
welder::overridable_virtuals
consteval std::vector< std::meta::info > overridable_virtuals(std::meta::info type)
Every overridable virtual slot of type — the ones welder routes through a trampoline — folding in vir...
Definition
virtuals.hpp:174
welder::bind_flat_spec
The stored form of a bind_flat mark (a plain tag — it carries no state).
Definition
virtuals.hpp:41
welder::diag::no_matching_virtual_slot
Thrown by virtual_slot (<welder/rods/python/trampoline.hpp>, reached through WELDER_PY_OVERRIDE_AS) w...
Definition
diag.hpp:64
src
welder
virtuals.hpp
Generated by
1.17.0