@@ -720,83 +720,63 @@ class virtual_ptr {
720720
721721 // ! Construct a `virtual_ptr` from another `virtual_ptr`
722722 // !
723- // ! Copy the object and v-table pointers from `other` to `this` .
723+ // ! Copy the object and v-table pointers from `other` to `this.
724724 // !
725- // ! @param other A virtual_ptr to a type-compatible object
725+ // ! `Other` is _not_ required to be a pointer to a polymorphic class.
726+ // !
727+ // ! @par Examples
728+ // !
729+ // ! Assigning from a plain virtual_ptr:
726730 // !
727- // ! @par Example
728731 // ! @code
729732 // ! struct Animal {}; // polymorphism not required
730733 // ! struct Dog : Animal {}; // polymorphism not required
731734 // ! BOOST_OPENMETHOD_CLASSES(Animal, Dog);
732735 // ! initialize();
733736 // !
734737 // ! Dog snoopy;
735- // ! const virtual_ptr<Dog> dog = final_virtual_ptr(snoopy);
738+ // ! virtual_ptr<Dog> dog = final_virtual_ptr(snoopy);
739+ // ! virtual_ptr<Animal> p{nullptr};
736740 // !
737- // ! virtual_ptr<Animal> p( dog) ;
741+ // ! p = dog;
738742 // !
739743 // ! BOOST_TEST(p.get() == &snoopy);
740744 // ! BOOST_TEST(p.vptr() == default_registry::static_vptr<Dog>);
741745 // ! @endcode
742746 // !
743- // ! @par Requirements
744- // !
745- // ! @li `Other\*` must be constructible from `Class\*`.
746- template <
747- class Other ,
748- typename = std::enable_if_t <std::is_constructible_v<
749- Class*, typename virtual_ptr<Other, Registry>::element_type*>>>
750- virtual_ptr (const virtual_ptr<Other, Registry>& other)
751- : vp(other.vp), obj(other.get()) {
752- }
753-
754- // ! Construct a `virtual_ptr` from another `virtual_ptr`
755- // !
756- // ! Copy the object and v-table pointers from `other` to `this`.
757- // !
758- // ! A plain `virtual_ptr` can be constructed from a smart virtual_ptr, as
759- // ! long as the smart pointer's element type is convertible to the plain
760- // ! pointer's element type.
761- // !
762- // ! `Other::element_type` is _not_ required to be a pointer to a polymorphic
763- // ! class.
747+ // ! Assigning from a smart virtual_ptr:
764748 // !
765- // ! @par Example
766749 // ! @code
767750 // ! struct Animal {}; // polymorphism not required
768751 // ! struct Dog : Animal {}; // polymorphism not required
769752 // ! BOOST_OPENMETHOD_CLASSES(Animal, Dog);
770753 // ! initialize();
771754 // !
772- // ! Dog snoopy;
773- // ! virtual_ptr<Dog> dog = final_virtual_ptr(snoopy);
774- // !
775- // ! virtual_ptr<Animal> p(dog);
755+ // ! virtual_ptr<std::shared_ptr<Animal>> snoopy = make_shared_virtual<Dog>();
756+ // ! virtual_ptr<Animal> p = snoopy;
776757 // !
777- // ! BOOST_TEST(p.get() == & snoopy);
758+ // ! BOOST_TEST(p.get() == snoopy.get() );
778759 // ! BOOST_TEST(p.vptr() == default_registry::static_vptr<Dog>);
779760 // ! @endcode
780761 // !
762+ // ! No construction of a smart `virtual_ptr` from a plain `virtual_ptr`:
763+ // !
764+ // ! @code
765+ // ! static_assert(
766+ // ! std::is_constructible_v<
767+ // ! shared_virtual_ptr<Animal>, virtual_ptr<Dog>> == false);
768+ // ! @endcode
769+ // !
781770 // ! @param other A virtual_ptr to a type-compatible object
782771 // !
783772 // ! @par Requirements
784- // !
785- // ! @li `Other\*` must be constructible from `Class\*`.
773+ // ! @li `Other`\'s object pointer must be assignable to a `Class\*`.
786774 template <
787775 class Other ,
788776 typename = std::enable_if_t <std::is_constructible_v<
789777 Class*, typename virtual_ptr<Other, Registry>::element_type*>>>
790- virtual_ptr (virtual_ptr<Other, Registry>& other)
778+ virtual_ptr (const virtual_ptr<Other, Registry>& other)
791779 : vp(other.vp), obj(other.get()) {
792- // Why is this needed? Consider this conversion conversion from
793- // smart to dumb pointer:
794- // virtual_ptr<std::shared_ptr<const Node>> p = ...;
795- // virtual_ptr<const Node> q = p;
796- // Since 'p' is not const, in the absence of this ctor,
797- // virtual_ptr(Other&) would be preferred to
798- // virtual_ptr(const virtual_ptr<Other, Registry>& other), and
799- // that is incorrect.
800780 }
801781
802782 // ! Assign a `virtual_ptr` from a reference to an object
@@ -843,7 +823,7 @@ class virtual_ptr {
843823 typename = std::enable_if_t <
844824 BOOST_OPENMETHOD_DETAIL_UNLESS_MRDOCS
845825 IsPolymorphic<Class, Registry> &&
846- std::is_assignable_v<Class*, Other*>>>
826+ std::is_assignable_v<Class*& , Other*>>>
847827 virtual_ptr& operator =(Other& other) {
848828 obj = &other;
849829 vp = detail::box_vptr<use_indirect_vptrs>(
@@ -893,7 +873,7 @@ class virtual_ptr {
893873 typename = std::enable_if_t <
894874 BOOST_OPENMETHOD_DETAIL_UNLESS_MRDOCS
895875 IsPolymorphic<Class, Registry> &&
896- std::is_assignable_v<Class*, Other*>>>
876+ std::is_assignable_v<Class*& , Other*>>>
897877 virtual_ptr& operator =(Other* other) {
898878 obj = other;
899879 vp = detail::box_vptr<use_indirect_vptrs>(
@@ -903,11 +883,14 @@ class virtual_ptr {
903883
904884 // ! Assign a `virtual_ptr` from another `virtual_ptr`
905885 // !
906- // ! The pointer to the v-table is copied from `other`.
886+ // ! Copy the object and v-table pointers from `other` to `this .
907887 // !
908888 // ! `Other` is _not_ required to be a pointer to a polymorphic class.
909889 // !
910- // ! @par Example
890+ // ! @par Examples
891+ // !
892+ // ! Assigning from a plain virtual_ptr:
893+ // !
911894 // ! @code
912895 // ! struct Animal {}; // polymorphism not required
913896 // ! struct Dog : Animal {}; // polymorphism not required
@@ -924,14 +907,39 @@ class virtual_ptr {
924907 // ! BOOST_TEST(p.vptr() == default_registry::static_vptr<Dog>);
925908 // ! @endcode
926909 // !
927- // ! @param other A virtual_ptr to a type-compatible polymorphic object
910+ // ! Assigning from a smart virtual_ptr:
911+ // !
912+ // ! @code
913+ // ! struct Animal {}; // polymorphism not required
914+ // ! struct Dog : Animal {}; // polymorphism not required
915+ // ! BOOST_OPENMETHOD_CLASSES(Animal, Dog);
916+ // ! initialize();
917+ // !
918+ // ! virtual_ptr<std::shared_ptr<Animal>> snoopy = make_shared_virtual<Dog>();
919+ // ! virtual_ptr<Animal> p;
920+ // !
921+ // ! p = snoopy;
922+ // !
923+ // ! BOOST_TEST(p.get() == snoopy.get());
924+ // ! BOOST_TEST(p.vptr() == default_registry::static_vptr<Dog>);
925+ // ! @endcode
926+ // !
927+ // ! No assignment from a plain `virtual_ptr` to a smart `virtual_ptr`:
928+ // !
929+ // ! @code
930+ // ! static_assert(
931+ // ! std::is_assignable_v<
932+ // ! shared_virtual_ptr<Animal>&, virtual_ptr<Dog>> == false);
933+ // ! @endcode
934+ // !
935+ // ! @param other A virtual_ptr to a type-compatible object
928936 // !
929937 // ! @par Requirements
930- // ! @li `Other\*` must be constructible from `Class\*`.
938+ // ! @li `Other`\'s object pointer must be assignable to a `Class\*`.
931939 template <
932940 class Other ,
933941 typename = std::enable_if_t <std::is_assignable_v<
934- Class*, typename virtual_ptr<Other, Registry>::element_type*>>>
942+ Class*& , typename virtual_ptr<Other, Registry>::element_type*>>>
935943 virtual_ptr& operator =(const virtual_ptr<Other, Registry>& other) {
936944 obj = other.get ();
937945 vp = other.vp ;
@@ -1283,43 +1291,6 @@ class virtual_ptr<
12831291 : vp(other.vp), obj(other.obj) {
12841292 }
12851293
1286- // ! Construct from a smart virtual pointer to a derived class
1287- // !
1288- // ! Copy the object and v-table pointers from `other`.
1289- // !
1290- // ! `Other` is _not_ required to be a pointer to a polymorphic class.
1291- // !
1292- // ! @par Example
1293- // ! @code
1294- // ! struct Animal {}; // polymorphism not required
1295- // ! struct Dog : Animal {}; // polymorphism not required
1296- // ! BOOST_OPENMETHOD_CLASSES(Animal, Dog);
1297- // ! initialize();
1298- // !
1299- // ! virtual_ptr<std::shared_ptr<Dog>> snoopy = make_shared_virtual<Dog>();
1300- // ! virtual_ptr<std::shared_ptr<Animal>> p = snoopy;
1301- // !
1302- // ! BOOST_TEST(snoopy.get() != nullptr);
1303- // ! BOOST_TEST(p.get() == snoopy.get());
1304- // ! BOOST_TEST(p.vptr() == default_registry::static_vptr<Dog>);
1305- // ! @endcode
1306- // !
1307- // ! @par Requirements
1308- // ! @li `SmartPtr` and `Other` must be instantiated from the same template -
1309- // ! e.g. both `std::shared_ptr` or both `std::unique_ptr`.
1310- // ! @li `Other` must be a virtual pointer to a class derived from
1311- // ! `element_type`.
1312- // ! @li `SmartPtr` must be constructible from `Other&`.
1313- template <
1314- class Other ,
1315- typename = std::enable_if_t <
1316- BOOST_OPENMETHOD_DETAIL_UNLESS_MRDOCS
1317- SameSmartPtr<SmartPtr, Other, Registry> &&
1318- std::is_constructible_v<SmartPtr, Other&>>>
1319- virtual_ptr (virtual_ptr<Other, Registry>& other)
1320- : vp(other.vp), obj(other.obj) {
1321- }
1322-
13231294 // ! Construct-move from a virtual pointer to a derived class
13241295 // !
13251296 // ! Move the object pointer from `other` to `this`. Copy the v-table pointer
0 commit comments