-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
weak_ptr: Make it possible to produce constant pointers #2226
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,8 @@ template<typename T> | |
class weak_ptr { | ||
template<typename U> | ||
friend class weakly_referencable; | ||
template <typename U> | ||
friend class weak_ptr; | ||
private: | ||
using hook_type = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>; | ||
hook_type _hook; | ||
|
@@ -59,7 +61,18 @@ private: | |
_hook.swap_nodes(o._hook); | ||
std::swap(_ptr, o._ptr); | ||
} | ||
|
||
public: | ||
template <typename U> | ||
requires std::convertible_to<U*, T*> | ||
weak_ptr(weak_ptr<U>&& o) | ||
{ | ||
if (o._ptr) { | ||
_ptr = std::exchange(o._ptr, nullptr); | ||
_hook.swap_nodes(o._hook); | ||
} | ||
} | ||
|
||
// Note: The default constructor's body is implemented as no-op | ||
// rather than `noexcept = default` due to a bug with gcc 9.3.1 | ||
// that deletes the constructor since boost::intrusive::list_member_hook | ||
|
@@ -139,6 +152,10 @@ public: | |
_ptr_list.push_back(ptr); | ||
return ptr; | ||
} | ||
|
||
weak_ptr<const T> weak_from_this() const noexcept { | ||
return const_cast<weakly_referencable*>(this)->weak_from_this(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xemul hi Pavel, i'd propose a different, but probably more standard compliant, and extensive solution to address this problem. from the standard, so instead of marking namespace internal {
// quote from
// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6,
//
// a pointer type Y* is said to be compatible with a pointer type T* when
// either Y* is convertible to T* or Y is U[N] and T is cv U[].
template <typename Y, typename T>
struct bounded_array_of : std::false_type {};
template <typename U, typename T, size_t N>
struct bounded_array_of<U[N], T> : std::is_same<std::remove_cv_t<T>, U[]> {};
template <typename Y, typename T>
concept pointer_type_compatible_with = (std::convertible_to<Y*, T*> ||
bounded_array_of<Y, T>::value);
}
///...
template<typename T>
class weak_ptr {
template<typename U>
friend class weakly_referencable;
template<typename U>
friend class weak_ptr;
private:
///...
template<internal::pointer_type_compatible_with<T> Y>
weak_ptr(const weak_ptr<Y>& o) noexcept {
if (o._ptr) {
swap(o._ptr->weak_from_this());
}
}
///...
template<typename T>
class weakly_referencable {
///...
weak_ptr<T> weak_from_this() const noexcept {
return const_cast<weakly_referencable*>(this)->weak_from_this();
}
}; for couple reasons:
please note, instead of using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
However at this point no more flexibility is requires from my perspective. In particular, your suggestion means that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think you misread the line of std::convertible_to<Y*, T*> also, my original intention was not "flexibility", but more about standard compliance and correctness. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, thank you, I misread the *'s :( However, I'm still concerned about the bounded_array. The template <typename Y, typename T>
concept pointer_type_compatible_with = (std::convertible_to<Y*, T*> ||
bounded_array_of<Y, T>::value); means that we can create There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, i was appreciating the design of the standard library, and completely ignored the connection between |
||
}; | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cosmetic: it's nicer to specify this as
weak_ptr(std::convertible_to<T&> auto&& o)
, as we don't introduce a variable U which is immediately forgotten (if it works).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't manage to make it work this-or-similar way.
In particular, this exact syntax fails like this
I guess it's because
std::convertible
applies to pointer type, while o's type is about weak_ptr<> over the type itself, so compiler doesn't match one against each otherThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it would know to convert references. But it's just cosmetic anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Is there anything else that prevents this patch from being merged? :)