@@ -156,35 +156,24 @@ struct remove_virtual_aux<virtual_<T>> {
156156template <typename T>
157157using 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
166164template <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
178171template <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
214203template <typename T, class Registry >
215- struct virtual_traits {
216- using virtual_type = void ;
217- };
204+ struct virtual_traits ;
218205
219206template <typename T, class Registry >
220207struct 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`.
482489template <class Registry , typename Arg>
483490inline 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-
527547template <class Class , class Registry , typename >
528548class 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.
816861template <class Class , class Registry >
817862class virtual_ptr <
818863 Class, Registry,
@@ -1254,6 +1299,29 @@ template<class Registry>
12541299using 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<
16131681void 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::
0 commit comments