Skip to content

Commit 3849208

Browse files
committed
refactor virtual_ptr
1 parent eefd991 commit 3849208

2 files changed

Lines changed: 68 additions & 83 deletions

File tree

include/boost/openmethod/core.hpp

Lines changed: 68 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,6 @@ struct parameter_traits {
191191
}
192192
};
193193

194-
template<typename T, class Registry>
195-
struct parameter_traits<virtual_<T>, Registry> : virtual_traits<T, Registry> {};
196-
197-
template<class Class, class Registry>
198-
struct parameter_traits<virtual_ptr<Class, Registry>, Registry>
199-
: virtual_traits<virtual_ptr<Class, Registry>, Registry> {};
200-
201-
template<class Class, class Registry>
202-
struct parameter_traits<const virtual_ptr<Class, Registry>&, Registry>
203-
: virtual_traits<const virtual_ptr<Class, Registry>&, Registry> {};
204-
205194
} // namespace detail
206195

207196
// =============================================================================
@@ -281,22 +270,29 @@ struct use_classes {
281270
template<class Registry, typename Argype>
282271
inline auto final_virtual_ptr(Argype&& obj);
283272

273+
template<
274+
class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY,
275+
typename = void>
276+
class virtual_ptr;
277+
284278
namespace detail {
285279

286280
template<class Class, class Registry>
287-
struct is_virtual<virtual_ptr<Class, Registry>> : std::true_type {};
281+
struct is_virtual<virtual_ptr<Class, Registry, void>> : std::true_type {};
288282

289283
template<class Class, class Registry>
290-
struct is_virtual<const virtual_ptr<Class, Registry>&> : std::true_type {};
284+
struct is_virtual<const virtual_ptr<Class, Registry, void>&> : std::true_type {
285+
};
291286

292287
template<typename>
293288
struct is_virtual_ptr_aux : std::false_type {};
294289

295290
template<class Class, class Registry>
296-
struct is_virtual_ptr_aux<virtual_ptr<Class, Registry>> : std::true_type {};
291+
struct is_virtual_ptr_aux<virtual_ptr<Class, Registry, void>> : std::true_type {
292+
};
297293

298294
template<class Class, class Registry>
299-
struct is_virtual_ptr_aux<const virtual_ptr<Class, Registry>&>
295+
struct is_virtual_ptr_aux<const virtual_ptr<Class, Registry, void>&>
300296
: std::true_type {};
301297

302298
template<typename T>
@@ -342,8 +338,11 @@ inline vptr_type null_vptr = nullptr;
342338

343339
} // namespace detail
344340

345-
template<class Class, class Registry, typename = void>
346-
class virtual_ptr_impl {
341+
template<class Class, class Registry, typename>
342+
class virtual_ptr {
343+
template<class, class, typename>
344+
friend class virtual_ptr;
345+
347346
public:
348347
static constexpr bool use_indirect_vptrs =
349348
Registry::template has_policy<policies::indirect_vptr>;
@@ -357,9 +356,9 @@ class virtual_ptr_impl {
357356
using element_type = Class;
358357
static constexpr bool is_smart_ptr = false;
359358

360-
virtual_ptr_impl() = default;
359+
virtual_ptr() = default;
361360

362-
explicit virtual_ptr_impl(std::nullptr_t)
361+
explicit virtual_ptr(std::nullptr_t)
363362
: vp(detail::box_vptr<use_indirect_vptrs>(detail::null_vptr)),
364363
obj(nullptr) {
365364
}
@@ -369,7 +368,7 @@ class virtual_ptr_impl {
369368
typename = std::enable_if_t<
370369
std::is_constructible_v<Class*, Other*> &&
371370
is_polymorphic<Registry, Class>>>
372-
virtual_ptr_impl(Other& other)
371+
virtual_ptr(Other& other)
373372
: vp(detail::box_vptr<use_indirect_vptrs>(
374373
detail::acquire_vptr<Registry>(other))),
375374
obj(&other) {
@@ -382,7 +381,7 @@ class virtual_ptr_impl {
382381
Class*,
383382
decltype(std::declval<virtual_ptr<Other, Registry>>().get())> &&
384383
is_polymorphic<Registry, Class>>>
385-
virtual_ptr_impl(Other* other)
384+
virtual_ptr(Other* other)
386385
: vp(detail::box_vptr<use_indirect_vptrs>(
387386
detail::acquire_vptr<Registry>(*other))),
388387
obj(other) {
@@ -393,7 +392,7 @@ class virtual_ptr_impl {
393392
typename = std::enable_if_t<std::is_constructible_v<
394393
Class*,
395394
decltype(std::declval<virtual_ptr<Other, Registry>>().get())>>>
396-
virtual_ptr_impl(const virtual_ptr<Other, Registry>& other)
395+
virtual_ptr(const virtual_ptr<Other, Registry>& other)
397396
: vp(other.vp), obj(other.get()) {
398397
}
399398

@@ -402,30 +401,30 @@ class virtual_ptr_impl {
402401
typename = std::enable_if_t<std::is_constructible_v<
403402
Class*,
404403
decltype(std::declval<virtual_ptr<Other, Registry>>().get())>>>
405-
virtual_ptr_impl(virtual_ptr_impl<Other, Registry>& other)
404+
virtual_ptr(virtual_ptr<Other, Registry>& other)
406405
: vp(other.vp), obj(other.get()) {
407406
// Why is this needed? Consider this conversion conversion from
408407
// smart to dumb pointer:
409408
// virtual_ptr<std::shared_ptr<const Node>> p = ...;
410409
// virtual_ptr<const Node> q = p;
411410
// Since 'p' is not const, in the absence of this ctor,
412-
// virtual_ptr_impl(Other&) would be preferred to
413-
// virtual_ptr_impl(const virtual_ptr<Other, Registry>& other), and
411+
// virtual_ptr(Other&) would be preferred to
412+
// virtual_ptr(const virtual_ptr<Other, Registry>& other), and
414413
// that is incorrect.
415414
}
416415

417416
template<
418417
class Other,
419418
typename = std::enable_if_t<std::is_constructible_v<Class*, Other*>>>
420-
virtual_ptr_impl(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
419+
virtual_ptr(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
421420
}
422421

423422
template<
424423
class Other,
425424
typename = std::enable_if_t<
426425
std::is_assignable_v<Class*, Other*> &&
427426
is_polymorphic<Registry, Class>>>
428-
virtual_ptr_impl& operator=(Other& other) {
427+
virtual_ptr& operator=(Other& other) {
429428
obj = &other;
430429
vp = detail::box_vptr<use_indirect_vptrs>(
431430
detail::acquire_vptr<Registry>(other));
@@ -437,7 +436,7 @@ class virtual_ptr_impl {
437436
typename = std::enable_if_t<
438437
std::is_assignable_v<Class*, Other*> &&
439438
is_polymorphic<Registry, Class>>>
440-
virtual_ptr_impl& operator=(Other* other) {
439+
virtual_ptr& operator=(Other* other) {
441440
obj = other;
442441
vp = detail::box_vptr<use_indirect_vptrs>(
443442
detail::acquire_vptr<Registry>(*other));
@@ -449,14 +448,13 @@ class virtual_ptr_impl {
449448
typename = std::enable_if_t<std::is_assignable_v<
450449
Class*,
451450
decltype(std::declval<virtual_ptr<Other, Registry>>().get())>>>
452-
virtual_ptr_impl&
453-
operator=(const virtual_ptr_impl<Other, Registry>& other) {
451+
virtual_ptr& operator=(const virtual_ptr<Other, Registry>& other) {
454452
obj = other.get();
455453
vp = other.vp;
456454
return *this;
457455
}
458456

459-
virtual_ptr_impl& operator=(std::nullptr_t) {
457+
virtual_ptr& operator=(std::nullptr_t) {
460458
obj = nullptr;
461459
vp = detail::box_vptr<use_indirect_vptrs>(detail::null_vptr);
462460
return *this;
@@ -518,50 +516,49 @@ constexpr bool same_smart_ptr =
518516
same_smart_ptr_aux<Class, Other, Registry>::value;
519517

520518
template<class Class, class Registry>
521-
class virtual_ptr_impl<
519+
class virtual_ptr<
522520
Class, Registry,
523521
std::void_t<
524522
typename virtual_traits<Class, Registry>::template rebind<Class>>> {
525523

524+
template<class, class, typename>
525+
friend class virtual_ptr;
526+
527+
template<class, class>
528+
friend struct virtual_traits;
529+
526530
public:
527531
using traits = virtual_traits<Class, Registry>;
528532
using element_type = typename Class::element_type;
529533

530534
static constexpr bool use_indirect_vptrs =
531535
Registry::template has_policy<policies::indirect_vptr>;
532536

533-
template<class, class>
534-
friend class virtual_ptr;
535-
template<class, class, typename>
536-
friend class virtual_ptr_impl;
537-
template<class, class>
538-
friend struct virtual_traits;
539-
540537
protected:
541538
std::conditional_t<use_indirect_vptrs, const vptr_type*, vptr_type> vp;
542539
Class obj;
543540

544541
public:
545542
static constexpr bool is_smart_ptr = true;
546543

547-
virtual_ptr_impl()
544+
virtual_ptr()
548545
: vp(detail::box_vptr<use_indirect_vptrs>(detail::null_vptr)) {
549546
}
550547

551-
explicit virtual_ptr_impl(std::nullptr_t)
548+
explicit virtual_ptr(std::nullptr_t)
552549
: vp(detail::box_vptr<use_indirect_vptrs>(detail::null_vptr)),
553550
obj(nullptr) {
554551
}
555552

556-
virtual_ptr_impl(const virtual_ptr_impl& other) = default;
553+
virtual_ptr(const virtual_ptr& other) = default;
557554

558555
template<
559556
class Other,
560557
typename = std::enable_if_t<
561558
same_smart_ptr<Class, Other, Registry> &&
562559
std::is_constructible_v<Class, const Other&> &&
563560
is_polymorphic<Registry, element_type>>>
564-
virtual_ptr_impl(const Other& other)
561+
virtual_ptr(const Other& other)
565562
: vp(detail::box_vptr<use_indirect_vptrs>(
566563
other ? detail::acquire_vptr<Registry>(*other)
567564
: detail::null_vptr)),
@@ -574,7 +571,7 @@ class virtual_ptr_impl<
574571
same_smart_ptr<Class, Other, Registry> &&
575572
std::is_constructible_v<Class, Other&> &&
576573
is_polymorphic<Registry, element_type>>>
577-
virtual_ptr_impl(Other& other)
574+
virtual_ptr(Other& other)
578575
: vp(detail::box_vptr<use_indirect_vptrs>(
579576
other ? detail::acquire_vptr<Registry>(*other)
580577
: detail::null_vptr)),
@@ -584,7 +581,7 @@ class virtual_ptr_impl<
584581
template<
585582
class Other,
586583
typename = std::enable_if_t<std::is_constructible_v<Class*, Other*>>>
587-
virtual_ptr_impl(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
584+
virtual_ptr(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
588585
}
589586

590587
template<
@@ -593,7 +590,7 @@ class virtual_ptr_impl<
593590
same_smart_ptr<Class, Other, Registry> &&
594591
std::is_constructible_v<Class, Other&&> &&
595592
is_polymorphic<Registry, element_type>>>
596-
virtual_ptr_impl(Other&& other)
593+
virtual_ptr(Other&& other)
597594
: vp(detail::box_vptr<use_indirect_vptrs>(
598595
other ? detail::acquire_vptr<Registry>(*other)
599596
: detail::null_vptr)),
@@ -605,7 +602,7 @@ class virtual_ptr_impl<
605602
typename = std::enable_if_t<
606603
same_smart_ptr<Class, Other, Registry> &&
607604
std::is_constructible_v<Class, const Other&>>>
608-
virtual_ptr_impl(const virtual_ptr_impl<Other, Registry>& other)
605+
virtual_ptr(const virtual_ptr<Other, Registry>& other)
609606
: vp(other.vp), obj(other.obj) {
610607
}
611608

@@ -614,12 +611,11 @@ class virtual_ptr_impl<
614611
typename = std::enable_if_t<
615612
same_smart_ptr<Class, Other, Registry> &&
616613
std::is_constructible_v<Class, Other&>>>
617-
virtual_ptr_impl(virtual_ptr_impl<Other, Registry>& other)
614+
virtual_ptr(virtual_ptr<Other, Registry>& other)
618615
: vp(other.vp), obj(other.obj) {
619616
}
620617

621-
virtual_ptr_impl(virtual_ptr_impl&& other)
622-
: vp(other.vp), obj(std::move(other.obj)) {
618+
virtual_ptr(virtual_ptr&& other) : vp(other.vp), obj(std::move(other.obj)) {
623619
other.vp = detail::box_vptr<use_indirect_vptrs>(detail::null_vptr);
624620
}
625621

@@ -628,17 +624,17 @@ class virtual_ptr_impl<
628624
typename = std::enable_if_t<
629625
same_smart_ptr<Class, Other, Registry> &&
630626
std::is_constructible_v<Class, Other&&>>>
631-
virtual_ptr_impl(virtual_ptr_impl<Other, Registry>&& other)
627+
virtual_ptr(virtual_ptr<Other, Registry>&& other)
632628
: vp(other.vp), obj(std::move(other.obj)) {
633629
other.vp = detail::box_vptr<use_indirect_vptrs>(detail::null_vptr);
634630
}
635631

636632
template<typename Arg>
637-
virtual_ptr_impl(Arg&& obj, decltype(vp) vp)
633+
virtual_ptr(Arg&& obj, decltype(vp) vp)
638634
: vp(vp), obj(std::forward<Arg>(obj)) {
639635
}
640636

641-
virtual_ptr_impl& operator=(std::nullptr_t) {
637+
virtual_ptr& operator=(std::nullptr_t) {
642638
obj = nullptr;
643639
vp = detail::box_vptr<use_indirect_vptrs>(detail::null_vptr);
644640
return *this;
@@ -650,7 +646,7 @@ class virtual_ptr_impl<
650646
same_smart_ptr<Class, Other, Registry> &&
651647
std::is_assignable_v<Class, const Other&> &&
652648
is_polymorphic<Registry, element_type>>>
653-
virtual_ptr_impl& operator=(const Other& other) {
649+
virtual_ptr& operator=(const Other& other) {
654650
obj = other;
655651
vp = detail::box_vptr<use_indirect_vptrs>(
656652
detail::acquire_vptr<Registry>(*other));
@@ -663,7 +659,7 @@ class virtual_ptr_impl<
663659
same_smart_ptr<Class, Other, Registry> &&
664660
std::is_assignable_v<Class, Other&&> &&
665661
is_polymorphic<Registry, element_type>>>
666-
virtual_ptr_impl& operator=(Other&& other) {
662+
virtual_ptr& operator=(Other&& other) {
667663
vp = detail::box_vptr<use_indirect_vptrs>(
668664
other ? detail::acquire_vptr<Registry>(*other) : detail::null_vptr);
669665
obj = std::move(other);
@@ -675,21 +671,20 @@ class virtual_ptr_impl<
675671
typename = std::enable_if_t<
676672
same_smart_ptr<Class, Other, Registry> &&
677673
std::is_assignable_v<Class, Other&>>>
678-
virtual_ptr_impl& operator=(virtual_ptr_impl<Other, Registry>& other) {
674+
virtual_ptr& operator=(virtual_ptr<Other, Registry>& other) {
679675
obj = other.obj;
680676
vp = other.vp;
681677
return *this;
682678
}
683679

684-
virtual_ptr_impl& operator=(const virtual_ptr_impl& other) = default;
680+
virtual_ptr& operator=(const virtual_ptr& other) = default;
685681

686682
template<
687683
class Other,
688684
typename = std::enable_if_t<
689685
same_smart_ptr<Class, Other, Registry> &&
690686
std::is_assignable_v<Class, const Other&>>>
691-
virtual_ptr_impl&
692-
operator=(const virtual_ptr_impl<Other, Registry>& other) {
687+
virtual_ptr& operator=(const virtual_ptr<Other, Registry>& other) {
693688
obj = other.obj;
694689
vp = other.vp;
695690
return *this;
@@ -700,7 +695,7 @@ class virtual_ptr_impl<
700695
typename = std::enable_if_t<
701696
same_smart_ptr<Class, Other, Registry> &&
702697
std::is_assignable_v<Class, Other&&>>>
703-
virtual_ptr_impl& operator=(virtual_ptr_impl<Other, Registry>&& other) {
698+
virtual_ptr& operator=(virtual_ptr<Other, Registry>&& other) {
704699
obj = std::move(other.obj);
705700
vp = other.vp;
706701
other.vp = detail::box_vptr<use_indirect_vptrs>(detail::null_vptr);
@@ -806,26 +801,6 @@ inline auto final_virtual_ptr(Class&& obj) {
806801
std::forward<Class>(obj));
807802
}
808803

809-
template<class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
810-
class virtual_ptr : public virtual_ptr_impl<Class, Registry> {
811-
using impl = virtual_ptr_impl<Class, Registry>;
812-
813-
public:
814-
using virtual_ptr_impl<Class, Registry>::virtual_ptr_impl;
815-
using element_type = typename impl::element_type;
816-
817-
template<class, class, typename>
818-
friend class virtual_ptr_impl;
819-
820-
template<
821-
typename Other,
822-
typename = std::enable_if_t<std::is_assignable_v<impl, Other>>>
823-
virtual_ptr& operator=(Other&& other) {
824-
impl::operator=(std::forward<Other>(other));
825-
return *this;
826-
}
827-
};
828-
829804
template<class Class>
830805
virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
831806

@@ -1270,6 +1245,19 @@ auto method<Name, ReturnType(Parameters...), Registry>::check_static_offset(
12701245
// -----------------------------------------------------------------------------
12711246
// method dispatch
12721247

1248+
namespace detail {
1249+
template<typename T, class Registry>
1250+
struct parameter_traits<virtual_<T>, Registry> : virtual_traits<T, Registry> {};
1251+
1252+
template<class Class, class Registry>
1253+
struct parameter_traits<virtual_ptr<Class, Registry, void>, Registry>
1254+
: virtual_traits<virtual_ptr<Class, Registry, void>, Registry> {};
1255+
1256+
template<class Class, class Registry>
1257+
struct parameter_traits<const virtual_ptr<Class, Registry, void>&, Registry>
1258+
: virtual_traits<const virtual_ptr<Class, Registry, void>&, Registry> {};
1259+
} // namespace detail
1260+
12731261
template<
12741262
typename Name, typename... Parameters, typename ReturnType, class Registry>
12751263
BOOST_FORCEINLINE auto

0 commit comments

Comments
 (0)