statically check that a class is polymorphic (where needed)

This commit is contained in:
Jean-Louis Leroy
2025-04-16 19:20:29 -04:00
committed by Jean-Louis Leroy
parent 1b350beedd
commit c610cab4a1
8 changed files with 80 additions and 13 deletions

View File

@@ -7,6 +7,9 @@ source:
[source,c++]
----
struct std_rtti : rtti {
template<class Class>
static constexpr auto is_polymorphic = std::is_polymorphic_v<Class>;
template<typename T>
static type_id static_type() {
return reinterpret_cast<type_id>(&typeid(T));
@@ -33,6 +36,9 @@ struct std_rtti : rtti {
};
----
* `is_polymorphic` is used to check if a class is polymorphic. This template is
required.
* `static_type` is used by class registration, by `virtual_ptr`{empty}'s "final"
constructs, and to format error and trace messages. `T` is not restricted to
the classes that appear as virtual parameters. This function is required.

View File

@@ -5,6 +5,9 @@
```c++
struct minimal_rtti : rtti {
template<class Class>
static constexpr bool is_polymorphic = false;
template<typename Class>
static auto static_type() -> type_id;
};
@@ -25,6 +28,15 @@ is not supported. Classes are not required to be polymorphic.
### Members
#### is_polymorphic
```c++
template<class Class>
static constexpr bool is_polymorphic = false;
```
This facet does not support polymorphic classes.
#### static_type
```c++

View File

@@ -21,6 +21,15 @@ an `ostream`-like object.
### Requirements
#### is_polymorphic
```c++
template<class Class>
static constexpr bool is_polymorphic;
```
`true` if `Class` is polymorphic.
#### static_type
```c++

View File

@@ -34,9 +34,12 @@ struct Dog : Animal {
namespace bom = boost::openmethod;
struct custom_rtti : bom::policies::rtti {
template<class T>
static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
template<typename T>
static auto static_type() -> bom::type_id {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return T::static_type;
} else {
return 0;
@@ -45,7 +48,7 @@ struct custom_rtti : bom::policies::rtti {
template<typename T>
static auto dynamic_type(const T& obj) -> bom::type_id {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return obj.type;
} else {
return 0;

View File

@@ -739,10 +739,16 @@ class virtual_ptr : public detail::virtual_ptr_impl<Class, Policy> {
std::is_base_of_v<element_type, other_class> ||
std::is_base_of_v<other_class, element_type>);
if constexpr (Policy::template has_facet<policies::runtime_checks>) {
if constexpr (
Policy::template has_facet<policies::runtime_checks> &&
Policy::template is_polymorphic<typename impl::traits::virtual_type> &&
Policy::template is_polymorphic<other_class>) {
// check that dynamic type == static type
auto static_type = Policy::template static_type<other_class>();
auto dynamic_type = Policy::dynamic_type(other_traits::peek(obj));
type_id dynamic_type;
dynamic_type = Policy::dynamic_type(other_traits::peek(obj));
if (dynamic_type != static_type) {
type_mismatch_error error;
@@ -1286,6 +1292,19 @@ method<Name(Parameters...), ReturnType, Policy>::resolve_multi_next(
// -----------------------------------------------------------------------------
// Error handling
namespace detail {
template<class Policy, class Class>
auto error_type_id(const Class& obj) {
if constexpr (Policy::template is_polymorphic<Class>) {
return Policy::template dynamic_type<Class>(obj);
} else {
return Policy::template static_type<void>();
}
}
} // namespace detail
template<
typename Name, typename... Parameters, typename ReturnType, class Policy>
BOOST_NORETURN auto
@@ -1298,7 +1317,7 @@ method<Name(Parameters...), ReturnType, Policy>::not_implemented_handler(
type_id types[sizeof...(args)];
auto ti_iter = types;
(...,
(*ti_iter++ = Policy::dynamic_type(
(*ti_iter++ = detail::error_type_id<Policy>(
detail::parameter_traits<Parameters, Policy>::peek(args))));
std::copy_n(
types,

View File

@@ -13,6 +13,9 @@ namespace openmethod {
namespace policies {
struct minimal_rtti : virtual rtti {
template<class Class>
static constexpr bool is_polymorphic = false;
template<typename T>
static auto static_type() -> type_id {
static char id;

View File

@@ -20,6 +20,9 @@ namespace policies {
struct std_rtti : virtual rtti {
#ifndef BOOST_NO_RTTI
template<class Class>
static constexpr bool is_polymorphic = std::is_polymorphic_v<Class>;
template<class Class>
static auto static_type() -> type_id {
auto tip = &typeid(Class);

View File

@@ -39,9 +39,12 @@ struct Cat : Animal {
};
struct custom_rtti : policies::rtti {
template<class T>
static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
template<typename T>
static auto static_type() {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return reinterpret_cast<type_id>(T::static_type);
} else {
return 0;
@@ -50,7 +53,7 @@ struct custom_rtti : policies::rtti {
template<typename T>
static auto dynamic_type(const T& obj) {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return reinterpret_cast<type_id>(obj.type);
} else {
return 0;
@@ -129,9 +132,12 @@ struct Cat : Animal {
};
struct custom_rtti : policies::rtti {
template<class T>
static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
template<typename T>
static auto static_type() {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return T::static_type;
} else {
return 666;
@@ -140,7 +146,7 @@ struct custom_rtti : policies::rtti {
template<typename T>
static auto dynamic_type(const T& obj) {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return obj.type;
} else {
return 666;
@@ -277,9 +283,12 @@ struct Cat : virtual Animal {
};
struct custom_rtti : policies::rtti {
template<class T>
static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
template<typename T>
static auto static_type() {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return T::static_type;
} else {
return 666;
@@ -288,7 +297,7 @@ struct custom_rtti : policies::rtti {
template<typename T>
static auto dynamic_type(const T& obj) {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return obj.type;
} else {
return 666;
@@ -418,9 +427,12 @@ struct Cat : Animal {
std::size_t Cat::static_type = ++Animal::last_type_id;
struct custom_rtti : policies::deferred_static_rtti {
template<class T>
static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
template<typename T>
static auto static_type() {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return T::static_type;
} else {
static type_id invalid = 0;
@@ -430,7 +442,7 @@ struct custom_rtti : policies::deferred_static_rtti {
template<typename T>
static auto dynamic_type(const T& obj) {
if constexpr (std::is_base_of_v<Animal, T>) {
if constexpr (is_polymorphic<T>) {
return obj.type;
} else {
return 666;