Skip to content

Commit e270359

Browse files
committed
doc
1 parent 0bef984 commit e270359

File tree

6 files changed

+151
-47
lines changed

6 files changed

+151
-47
lines changed

include/boost/openmethod/core.hpp

Lines changed: 104 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -156,35 +156,24 @@ struct remove_virtual_aux<virtual_<T>> {
156156
template<typename T>
157157
using remove_virtual_ = typename remove_virtual_aux<T>::type;
158158

159-
template<typename T, class Registry>
160-
using virtual_type = typename virtual_traits<T, Registry>::virtual_type;
161-
162-
template<typename MethodArgList>
163-
using virtual_types = boost::mp11::mp_transform<
164-
remove_virtual_, boost::mp11::mp_filter<detail::is_virtual, MethodArgList>>;
159+
template<typename T, class Registry, typename = void>
160+
struct virtual_type_aux {
161+
using type = void;
162+
};
165163

166164
template<typename T, class Registry>
167-
struct parameter_traits {
168-
static auto peek(const T&) {
169-
return nullptr;
170-
}
171-
172-
template<typename>
173-
static auto cast(T value) -> T {
174-
return value;
175-
}
165+
struct virtual_type_aux<
166+
T, Registry,
167+
std::void_t<typename virtual_traits<T, Registry>::virtual_type>> {
168+
using type = typename virtual_traits<T, Registry>::virtual_type;
176169
};
177170

178171
template<typename T, class Registry>
179-
struct parameter_traits<virtual_<T>, Registry> : virtual_traits<T, Registry> {};
172+
using virtual_type = typename virtual_type_aux<T, Registry>::type;
180173

181-
template<class Class, class Registry>
182-
struct parameter_traits<virtual_ptr<Class, Registry, void>, Registry>
183-
: virtual_traits<virtual_ptr<Class, Registry, void>, Registry> {};
184-
185-
template<class Class, class Registry>
186-
struct parameter_traits<const virtual_ptr<Class, Registry, void>&, Registry>
187-
: virtual_traits<const virtual_ptr<Class, Registry, void>&, Registry> {};
174+
template<typename MethodArgList>
175+
using virtual_types = boost::mp11::mp_transform<
176+
remove_virtual_, boost::mp11::mp_filter<detail::is_virtual, MethodArgList>>;
188177

189178
} // namespace detail
190179

@@ -212,9 +201,7 @@ BOOST_OPENMETHOD_CLOSE_NAMESPACE_DETAIL_UNLESS_MRDOCS
212201
// virtual_traits
213202

214203
template<typename T, class Registry>
215-
struct virtual_traits {
216-
using virtual_type = void;
217-
};
204+
struct virtual_traits;
218205

219206
template<typename T, class Registry>
220207
struct virtual_traits<T&, Registry> {
@@ -479,6 +466,26 @@ inline vptr_type null_vptr = nullptr;
479466

480467
} // namespace detail
481468

469+
//! Create a `virtual_ptr` for an object of an exact known type
470+
//!
471+
//! `final_virtual_ptr` creates a `virtual_ptr` to an object, setting its
472+
//! v-table pointer according to the declared type of its argument. It assumes
473+
//! that the static and dynamic types are the same. The v-table pointer is
474+
//! initialized from the `Policy::static_vptr` for the class, which needs
475+
//! not be polymorphic.
476+
//!
477+
//! @para Errors If the registry has runtime checks enabled, and the argument is
478+
//! a class type that is polymorphic according to the registry's `rtti` policy,
479+
//! a check is performed to verify that the static and dynamic types are indeed
480+
//! the same. If they are not, and if the registry contains an @ref
481+
//! error_handler policy, its
482+
//! @ref error function is called with a @ref final_error value, then the
483+
//! program is terminated with @ref abort.
484+
//!
485+
//! @tparam Registry The registry in which the class is registered.
486+
//! @tparam Arg The type of the argument.
487+
//! @param obj A reference to an object.
488+
//! @return A `virtual_ptr<Class, Registry>` pointing to `obj`.
482489
template<class Registry, typename Arg>
483490
inline auto final_virtual_ptr(Arg&& obj) {
484491
using namespace detail;
@@ -518,12 +525,25 @@ inline auto final_virtual_ptr(Arg&& obj) {
518525
std::forward<Arg>(obj));
519526
}
520527

521-
//! Wide pointer combining a pointers to an object and its v-table
528+
//! Wide pointer combining pointers to an object and its v-table
529+
//!
530+
//! `virtual_ptr` is a wide pointer that combines a pointer to an object and a
531+
//! pointer to its v-table. It can be constructed from a reference, a pointer,
532+
//! or another `virtual_ptr`.
533+
//!
534+
//! Calls to methods via `virtual_ptr` are as fast as ordinary virtual function
535+
//! calls (typically two instructions).
536+
//!
537+
//! @par Requirements
538+
//!
539+
//! @li A `virtual_traits<Class&>` specialization must exist and provide the
540+
//! required members.
541+
//! @li `Class` must be a class type, possibly cv-qualified. It must be
542+
//! registered in `Registry`.
522543
//!
523-
//! @tparam Class The class of the object.
524-
//! @tparam Registry The registry in which `Class` is registered.
544+
//! @tparam Class The class of the object, possibly cv-qualified
545+
//! @tparam Registry The registry in which `Class` is registered
525546
//! @tparam unnamed Implementation defined, do not provide.
526-
527547
template<class Class, class Registry, typename>
528548
class virtual_ptr {
529549

@@ -549,6 +569,9 @@ class virtual_ptr {
549569
}
550570

551571
public:
572+
//! The type of the object pointed to
573+
//!
574+
//! This is the same as `Class`.
552575
using element_type = Class;
553576

554577
//! Default constructor
@@ -794,25 +817,47 @@ class virtual_ptr {
794817
return *get();
795818
}
796819

820+
//! Cast to another `virtual_ptr` type
821+
//! @tparam Other The target class of the cast
822+
//! @return A `virtual_ptr<Other, Registry>` pointing to the same object
823+
//! @par Requirements
824+
//! @li `Other` must be a base or derived class of `Class`.
797825
template<class Other>
798826
auto cast() const -> decltype(auto) {
799-
static_assert(
800-
std::is_base_of_v<Class, Other> || std::is_base_of_v<Other, Class>);
801-
802827
return virtual_ptr<Other, Registry>(
803828
traits::template cast<Other&>(*obj), vp);
804829
}
805830

831+
//! Construct a `virtual_ptr` from a reference to an object
832+
//!
833+
//! This function forwards to @ref final_virtual_ptr.
834+
//!
835+
//! @tparam Other The type of the argument
836+
//! @param obj A reference to an object
837+
//! @return A `virtual_ptr<Class, Registry>` pointing to `obj`
806838
template<class Other>
807839
static auto final(Other&& obj) {
808840
return final_virtual_ptr<Registry>(std::forward<Other>(obj));
809841
}
810842

843+
//! Get the v-table pointer
844+
//! @return The v-table pointer
811845
auto vptr() const {
812846
return detail::unbox_vptr(this->vp);
813847
}
814848
};
815849

850+
//! Wide pointer combining a smart pointer to an object and its v-table
851+
//!
852+
//! This specialization of `virtual_ptr` uses a smart pointer to the object,
853+
//! instead of a plain pointer.
854+
//!
855+
//! Calls to methods via `virtual_ptr` are as fast as ordinary virtual function
856+
//! calls (typically two instructions).
857+
//!
858+
//! @tparam Class The class of the object, possibly cv-qualified
859+
//! @tparam Registry The registry in which `Class` is registered
860+
//! @tparam unnamed Implementation defined, do not provide.
816861
template<class Class, class Registry>
817862
class virtual_ptr<
818863
Class, Registry,
@@ -1254,6 +1299,29 @@ template<class Registry>
12541299
using method_base = std::conditional_t<
12551300
Registry::has_deferred_static_rtti, deferred_method_info, method_info>;
12561301

1302+
template<typename T, class Registry>
1303+
struct parameter_traits {
1304+
static auto peek(const T&) {
1305+
return nullptr;
1306+
}
1307+
1308+
template<typename>
1309+
static auto cast(T value) -> T {
1310+
return value;
1311+
}
1312+
};
1313+
1314+
template<typename T, class Registry>
1315+
struct parameter_traits<virtual_<T>, Registry> : virtual_traits<T, Registry> {};
1316+
1317+
template<class Class, class Registry>
1318+
struct parameter_traits<virtual_ptr<Class, Registry, void>, Registry>
1319+
: virtual_traits<virtual_ptr<Class, Registry, void>, Registry> {};
1320+
1321+
template<class Class, class Registry>
1322+
struct parameter_traits<const virtual_ptr<Class, Registry, void>&, Registry>
1323+
: virtual_traits<const virtual_ptr<Class, Registry, void>&, Registry> {};
1324+
12571325
} // namespace detail
12581326

12591327
//! Specialized with name, signature and return type
@@ -1613,8 +1681,8 @@ template<
16131681
void method<Name, ReturnType(Parameters...), Registry>::resolve_type_ids() {
16141682
using namespace detail;
16151683
this->method_type_id = rtti::template static_type<method>();
1616-
this->return_type_id = rtti::template static_type<
1617-
typename virtual_traits<ReturnType, Registry>::virtual_type>();
1684+
this->return_type_id =
1685+
rtti::template static_type<virtual_type<ReturnType, Registry>>();
16181686
init_type_ids<
16191687
Registry,
16201688
mp11::mp_transform_q<
@@ -1963,7 +2031,7 @@ void method<Name, ReturnType(Parameters...), Registry>::override_impl<
19632031
using namespace detail;
19642032

19652033
this->return_type = Registry::rtti::template static_type<
1966-
typename virtual_traits<FnReturnType, Registry>::virtual_type>();
2034+
virtual_type<FnReturnType, Registry>>();
19672035
this->type = Registry::rtti::template static_type<decltype(Function)>();
19682036
using Thunk = thunk<Function, decltype(Function)>;
19692037
detail::

include/boost/openmethod/detail/types.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,31 +87,59 @@ struct hash_search_error : openmethod_error {
8787
auto write(Stream& os) const -> void;
8888
};
8989

90+
//! An error indicating that no valid overrider exists for the given virtual
91+
//! tuple.
9092
struct call_error : openmethod_error {
93+
//! The type_id of method that was called.
9194
type_id method;
95+
//! The number of @em virtual arguments in the call.
9296
std::size_t arity;
97+
//! The maximum size of `types`.
9398
static constexpr std::size_t max_types = 16;
99+
//! The type_ids of the arguments.
94100
type_id types[max_types];
95101

96102
protected:
97103
template<class Registry, class Stream>
98104
auto write_aux(Stream& os, const char* subtype) const -> void;
99105
};
100106

107+
//! An error indicating that no overrider exists for the given virtual tuple.
108+
//!
109+
//! @see @ref call_error for data members.
101110
struct not_implemented_error : call_error {
111+
//! Write a short description to an output stream.
112+
//! @param os The output stream.
113+
//! @tparam Registry The registry type.
114+
//! @tparam Stream A @ref LightweightOutputStream.
102115
template<class Registry, class Stream>
103116
auto write(Stream& os) const -> void {
104117
write_aux<Registry>(os, "not implemented");
105118
}
106119
};
107120

121+
//! An error indicating that a method call is ambiguous.
122+
//!
123+
//! @see @ref call_error for data members.
108124
struct ambiguous_error : call_error {
125+
//! Write a short description to an output stream.
126+
//! @param os The output stream.
127+
//! @tparam Registry The registry type.
128+
//! @tparam Stream A @ref LightweightOutputStream.
109129
template<class Registry, class Stream>
110130
auto write(Stream& os) const -> void {
111131
write_aux<Registry>(os, "ambiguous");
112132
}
113133
};
114134

135+
//! Static and dynamic type mismatch in a "final" construct.
136+
//!
137+
//! If runtime checks are enabled, the "final" construct checks that the static
138+
//! and dynamic types of the object, as reported by the `rtti` policy, are the
139+
//! same. If they are not, and if the registry contains an @ref error_handler
140+
//! policy, its @ref error function is called with a `final_error` object, then
141+
//! the program is terminated with
142+
//! @ref abort.
115143
struct final_error : openmethod_error {
116144
type_id static_type, dynamic_type;
117145

include/boost/openmethod/registry.hpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ namespace boost::openmethod {
6262
//! and enabling some sections of code. They can be used as-is, without the need
6363
//! for subclassing.
6464

65+
#ifdef __MRDOCS__
66+
67+
//! Requirements for LightweightOutputStream (exposition only)
68+
struct LightweightOutputStream {
69+
LightweightOutputStream& operator<<(const char* str);
70+
LightweightOutputStream& operator<<(const std::string_view& view);
71+
LightweightOutputStream& operator<<(const void* value);
72+
LightweightOutputStream& operator<<(std::size_t value);
73+
};
74+
75+
#endif
76+
6577
namespace policies {
6678

6779
#ifdef __MRDOCS__
@@ -79,14 +91,6 @@ struct Policy : PolicyCategory {
7991
struct fn;
8092
};
8193

82-
//! Requirements for LightweightOutputStream (exposition only)
83-
struct LightweightOutputStream {
84-
LightweightOutputStream& operator<<(const char* str);
85-
LightweightOutputStream& operator<<(const std::string_view& view);
86-
LightweightOutputStream& operator<<(const void* value);
87-
LightweightOutputStream& operator<<(std::size_t value);
88-
};
89-
9094
//! Requirements for IdsToVptr (exposition only)
9195
//!
9296
struct IdsToVptr {

test/test_core.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ static_assert(
4545
static_assert(std::is_same_v<
4646
virtual_traits<base&&, default_registry>::virtual_type, base>);
4747

48-
static_assert(
49-
std::is_same_v<virtual_traits<int, default_registry>::virtual_type, void>);
50-
5148
static_assert(std::is_same_v<
5249
mp11::mp_filter<
5350
is_virtual, mp11::mp_list<virtual_<a&>, b, virtual_<c&>>>,

test/test_n2216.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ BOOST_OPENMETHOD_OVERRIDE(
4545
return std::make_unique<matrix>();
4646
}
4747

48+
static_assert(std::is_same_v<
49+
detail::virtual_type<std::unique_ptr<matrix>, n2216>,
50+
matrix>);
51+
4852
BOOST_AUTO_TEST_CASE(covariant_return_type) {
4953
auto compiler = n2216::initialize();
5054
BOOST_TEST(compiler.report.ambiguous == 0u);

test/test_virtual_ptr_value_semantics.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(
1313
static_assert(
1414
std::is_same_v<
1515
typename virtual_ptr<Animal, Registry>::element_type, Animal>);
16+
static_assert(std::is_same_v<
17+
typename virtual_ptr<const Animal, Registry>::element_type,
18+
const Animal>);
1619
static_assert(std::is_same_v<
1720
decltype(std::declval<virtual_ptr<Animal, Registry>>().get()),
1821
Animal*>);

0 commit comments

Comments
 (0)