welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
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
30namespace welder::inline v0 {
31
32// --- bind_flat: opt out of trampoline support for a virtual type -------------
33
42
58inline constexpr bind_flat_spec bind_flat{};
59
63consteval 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
78consteval 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
83namespace detail {
84
94consteval 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
135consteval 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
174consteval 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
213consteval 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;
220}
221
232consteval std::size_t virtual_slot_count(std::meta::info type) {
233 return overridable_virtuals(type).size();
234}
235
239consteval bool has_virtual_methods(std::meta::info type) {
240 return !overridable_virtuals(type).empty();
241}
242
243} // namespace welder::inline v0
welder's consteval diagnostics, collected in one place: every hand-rolled compile-time error the libr...
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
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
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
constexpr bind_flat_spec bind_flat
Mark a virtual entity as deliberately bound non-overridably.
Definition virtuals.hpp:58
consteval bool has_virtual_methods(std::meta::info type)
Does type declare or inherit any overridable virtual method?
Definition virtuals.hpp:239
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
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
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
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
The stored form of a bind_flat mark (a plain tag — it carries no state).
Definition virtuals.hpp:41
Thrown by virtual_slot (<welder/rods/python/trampoline.hpp>, reached through WELDER_PY_OVERRIDE_AS) w...
Definition diag.hpp:64