A free-standing weak_ptr equivalent to handle lifetime of non-shared callback objects
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I've been finding myself wanting the following pattern recently:
void perform_async_operation(std::function<void(int)>);
class some_class
public:
void foo()
perform_async_operation([this](int result)
data_ = result;
);
private:
int data_;
;
Now, the issue here is that the lifetime of some_class
if fully disconnected from when the callback will be invoked, and I do not want to move to shared ownership to put a shared_ptr
in the lambda (like how the boost::ASIO examples handle that situation).
I do, however, have a saving grace: I know for certain that the callback will be invoked in the same thread that manages the lifetime of some_class
.
In order to solve this, I've created a bastardized version of weak_ptr
(with a matching equivalent of enabled_shared_from_this
) that does not require the object to be managed by a shared_ptr
in the first place.
#ifndef SLT_WEAK_REF_INCLUDED_H
#define SLT_WEAK_REF_INCLUDED_H
#include <memory>
template <typename T>
class weak_ref
public:
weak_ref(std::shared_ptr<T*> weak_data) : weak_data_(std::move(weak_data))
operator bool() const return *weak_data_ != nullptr;
T* operator->() const return *weak_data_;
private:
// Can be safely assumed to always be set.
std::shared_ptr<T*> weak_data_;
;
template <typename CRTP>
class enable_weak_ref
public:
enable_weak_ref() = default;
enable_weak_ref(enable_weak_ref&& rhs)
: weak_data_(std::move(rhs.weak_data_))
if (weak_data_)
*weak_data_ = this;
enable_weak_ref& operator=(enable_weak_ref&& rhs)
weak_data_ = std::move(rhs.weak_data_);
if (weak_data_)
*weak_data_ = static_cast<CRTP*>(this);
// explicitely do nothing
enable_weak_ref(enable_weak_ref const& rhs)
enable_weak_ref& operator=(enable_weak_ref const&)
~enable_weak_ref()
if (weak_data_)
*weak_data_ = nullptr;
weak_ref<CRTP> get_weak_ref()
if (!weak_data_)
weak_data_ = std::make_shared<CRTP*>(static_cast<CRTP*>(this));
return weak_ref<CRTP>(weak_data_);
private:
// TODO: perhaps switch to a simple manually ref-counted type here.
// instead of the overkill shared_ptr<>
std::shared_ptr<CRTP*> weak_data_;
;
#endif
sample usage:
#include "weak_ref.h"
#include <queue>
#include <iostream>
#include <functional>
std::queue<std::function<void(int)>> queue_;
void queue_delayed(std::function<void(int)> cb)
queue_.emplace(std::move(cb));
class my_class : public enable_weak_ref<my_class>
public:
my_class()
queue_delayed([ref = get_weak_ref()](int v)
if(ref)
std::cout << "passed " << v << std::endl;
ref->value = v;
else
std::cout << "saved " << v << std::endl;
);
int value = 0;
;
int main()
my_class a;
queue_.front()(12);
queue_.pop();
my_class b;
queue_.front()(5);
queue_.pop();
return 0;
Notes:
- Moving an object in a lambda is a C++14 feature, without which, a lot of back-and-forth ref-counting happens.
- As mentioned, this is intentionally not thread-safe. Thread safety can be added if anyone needs it eventually.
Issues:
- Is there a nicer way to tackle this I'm overlooking here?
weak_ref
is very weak name, I'd gladly welcome better suggestions.- As always, comments on general code quality are most desired.
c++ memory-management c++14
add a comment |Â
up vote
3
down vote
favorite
I've been finding myself wanting the following pattern recently:
void perform_async_operation(std::function<void(int)>);
class some_class
public:
void foo()
perform_async_operation([this](int result)
data_ = result;
);
private:
int data_;
;
Now, the issue here is that the lifetime of some_class
if fully disconnected from when the callback will be invoked, and I do not want to move to shared ownership to put a shared_ptr
in the lambda (like how the boost::ASIO examples handle that situation).
I do, however, have a saving grace: I know for certain that the callback will be invoked in the same thread that manages the lifetime of some_class
.
In order to solve this, I've created a bastardized version of weak_ptr
(with a matching equivalent of enabled_shared_from_this
) that does not require the object to be managed by a shared_ptr
in the first place.
#ifndef SLT_WEAK_REF_INCLUDED_H
#define SLT_WEAK_REF_INCLUDED_H
#include <memory>
template <typename T>
class weak_ref
public:
weak_ref(std::shared_ptr<T*> weak_data) : weak_data_(std::move(weak_data))
operator bool() const return *weak_data_ != nullptr;
T* operator->() const return *weak_data_;
private:
// Can be safely assumed to always be set.
std::shared_ptr<T*> weak_data_;
;
template <typename CRTP>
class enable_weak_ref
public:
enable_weak_ref() = default;
enable_weak_ref(enable_weak_ref&& rhs)
: weak_data_(std::move(rhs.weak_data_))
if (weak_data_)
*weak_data_ = this;
enable_weak_ref& operator=(enable_weak_ref&& rhs)
weak_data_ = std::move(rhs.weak_data_);
if (weak_data_)
*weak_data_ = static_cast<CRTP*>(this);
// explicitely do nothing
enable_weak_ref(enable_weak_ref const& rhs)
enable_weak_ref& operator=(enable_weak_ref const&)
~enable_weak_ref()
if (weak_data_)
*weak_data_ = nullptr;
weak_ref<CRTP> get_weak_ref()
if (!weak_data_)
weak_data_ = std::make_shared<CRTP*>(static_cast<CRTP*>(this));
return weak_ref<CRTP>(weak_data_);
private:
// TODO: perhaps switch to a simple manually ref-counted type here.
// instead of the overkill shared_ptr<>
std::shared_ptr<CRTP*> weak_data_;
;
#endif
sample usage:
#include "weak_ref.h"
#include <queue>
#include <iostream>
#include <functional>
std::queue<std::function<void(int)>> queue_;
void queue_delayed(std::function<void(int)> cb)
queue_.emplace(std::move(cb));
class my_class : public enable_weak_ref<my_class>
public:
my_class()
queue_delayed([ref = get_weak_ref()](int v)
if(ref)
std::cout << "passed " << v << std::endl;
ref->value = v;
else
std::cout << "saved " << v << std::endl;
);
int value = 0;
;
int main()
my_class a;
queue_.front()(12);
queue_.pop();
my_class b;
queue_.front()(5);
queue_.pop();
return 0;
Notes:
- Moving an object in a lambda is a C++14 feature, without which, a lot of back-and-forth ref-counting happens.
- As mentioned, this is intentionally not thread-safe. Thread safety can be added if anyone needs it eventually.
Issues:
- Is there a nicer way to tackle this I'm overlooking here?
weak_ref
is very weak name, I'd gladly welcome better suggestions.- As always, comments on general code quality are most desired.
c++ memory-management c++14
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I've been finding myself wanting the following pattern recently:
void perform_async_operation(std::function<void(int)>);
class some_class
public:
void foo()
perform_async_operation([this](int result)
data_ = result;
);
private:
int data_;
;
Now, the issue here is that the lifetime of some_class
if fully disconnected from when the callback will be invoked, and I do not want to move to shared ownership to put a shared_ptr
in the lambda (like how the boost::ASIO examples handle that situation).
I do, however, have a saving grace: I know for certain that the callback will be invoked in the same thread that manages the lifetime of some_class
.
In order to solve this, I've created a bastardized version of weak_ptr
(with a matching equivalent of enabled_shared_from_this
) that does not require the object to be managed by a shared_ptr
in the first place.
#ifndef SLT_WEAK_REF_INCLUDED_H
#define SLT_WEAK_REF_INCLUDED_H
#include <memory>
template <typename T>
class weak_ref
public:
weak_ref(std::shared_ptr<T*> weak_data) : weak_data_(std::move(weak_data))
operator bool() const return *weak_data_ != nullptr;
T* operator->() const return *weak_data_;
private:
// Can be safely assumed to always be set.
std::shared_ptr<T*> weak_data_;
;
template <typename CRTP>
class enable_weak_ref
public:
enable_weak_ref() = default;
enable_weak_ref(enable_weak_ref&& rhs)
: weak_data_(std::move(rhs.weak_data_))
if (weak_data_)
*weak_data_ = this;
enable_weak_ref& operator=(enable_weak_ref&& rhs)
weak_data_ = std::move(rhs.weak_data_);
if (weak_data_)
*weak_data_ = static_cast<CRTP*>(this);
// explicitely do nothing
enable_weak_ref(enable_weak_ref const& rhs)
enable_weak_ref& operator=(enable_weak_ref const&)
~enable_weak_ref()
if (weak_data_)
*weak_data_ = nullptr;
weak_ref<CRTP> get_weak_ref()
if (!weak_data_)
weak_data_ = std::make_shared<CRTP*>(static_cast<CRTP*>(this));
return weak_ref<CRTP>(weak_data_);
private:
// TODO: perhaps switch to a simple manually ref-counted type here.
// instead of the overkill shared_ptr<>
std::shared_ptr<CRTP*> weak_data_;
;
#endif
sample usage:
#include "weak_ref.h"
#include <queue>
#include <iostream>
#include <functional>
std::queue<std::function<void(int)>> queue_;
void queue_delayed(std::function<void(int)> cb)
queue_.emplace(std::move(cb));
class my_class : public enable_weak_ref<my_class>
public:
my_class()
queue_delayed([ref = get_weak_ref()](int v)
if(ref)
std::cout << "passed " << v << std::endl;
ref->value = v;
else
std::cout << "saved " << v << std::endl;
);
int value = 0;
;
int main()
my_class a;
queue_.front()(12);
queue_.pop();
my_class b;
queue_.front()(5);
queue_.pop();
return 0;
Notes:
- Moving an object in a lambda is a C++14 feature, without which, a lot of back-and-forth ref-counting happens.
- As mentioned, this is intentionally not thread-safe. Thread safety can be added if anyone needs it eventually.
Issues:
- Is there a nicer way to tackle this I'm overlooking here?
weak_ref
is very weak name, I'd gladly welcome better suggestions.- As always, comments on general code quality are most desired.
c++ memory-management c++14
I've been finding myself wanting the following pattern recently:
void perform_async_operation(std::function<void(int)>);
class some_class
public:
void foo()
perform_async_operation([this](int result)
data_ = result;
);
private:
int data_;
;
Now, the issue here is that the lifetime of some_class
if fully disconnected from when the callback will be invoked, and I do not want to move to shared ownership to put a shared_ptr
in the lambda (like how the boost::ASIO examples handle that situation).
I do, however, have a saving grace: I know for certain that the callback will be invoked in the same thread that manages the lifetime of some_class
.
In order to solve this, I've created a bastardized version of weak_ptr
(with a matching equivalent of enabled_shared_from_this
) that does not require the object to be managed by a shared_ptr
in the first place.
#ifndef SLT_WEAK_REF_INCLUDED_H
#define SLT_WEAK_REF_INCLUDED_H
#include <memory>
template <typename T>
class weak_ref
public:
weak_ref(std::shared_ptr<T*> weak_data) : weak_data_(std::move(weak_data))
operator bool() const return *weak_data_ != nullptr;
T* operator->() const return *weak_data_;
private:
// Can be safely assumed to always be set.
std::shared_ptr<T*> weak_data_;
;
template <typename CRTP>
class enable_weak_ref
public:
enable_weak_ref() = default;
enable_weak_ref(enable_weak_ref&& rhs)
: weak_data_(std::move(rhs.weak_data_))
if (weak_data_)
*weak_data_ = this;
enable_weak_ref& operator=(enable_weak_ref&& rhs)
weak_data_ = std::move(rhs.weak_data_);
if (weak_data_)
*weak_data_ = static_cast<CRTP*>(this);
// explicitely do nothing
enable_weak_ref(enable_weak_ref const& rhs)
enable_weak_ref& operator=(enable_weak_ref const&)
~enable_weak_ref()
if (weak_data_)
*weak_data_ = nullptr;
weak_ref<CRTP> get_weak_ref()
if (!weak_data_)
weak_data_ = std::make_shared<CRTP*>(static_cast<CRTP*>(this));
return weak_ref<CRTP>(weak_data_);
private:
// TODO: perhaps switch to a simple manually ref-counted type here.
// instead of the overkill shared_ptr<>
std::shared_ptr<CRTP*> weak_data_;
;
#endif
sample usage:
#include "weak_ref.h"
#include <queue>
#include <iostream>
#include <functional>
std::queue<std::function<void(int)>> queue_;
void queue_delayed(std::function<void(int)> cb)
queue_.emplace(std::move(cb));
class my_class : public enable_weak_ref<my_class>
public:
my_class()
queue_delayed([ref = get_weak_ref()](int v)
if(ref)
std::cout << "passed " << v << std::endl;
ref->value = v;
else
std::cout << "saved " << v << std::endl;
);
int value = 0;
;
int main()
my_class a;
queue_.front()(12);
queue_.pop();
my_class b;
queue_.front()(5);
queue_.pop();
return 0;
Notes:
- Moving an object in a lambda is a C++14 feature, without which, a lot of back-and-forth ref-counting happens.
- As mentioned, this is intentionally not thread-safe. Thread safety can be added if anyone needs it eventually.
Issues:
- Is there a nicer way to tackle this I'm overlooking here?
weak_ref
is very weak name, I'd gladly welcome better suggestions.- As always, comments on general code quality are most desired.
c++ memory-management c++14
edited Jan 4 at 6:44
asked Jan 4 at 2:45
Frank
2,947319
2,947319
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
I never saw a similar pattern so it was really interesting to understand your code !
First, about the name weak_ref
, it implies that it has the syntax of a reference
, but it is not the case (for instance, operator->
is for pointers). I personnaly named it something like ptr_to_instance
.
Then, it seems the weak_ref
should not be used on its own, without calling enable_weak_ref::get_weak_ref()
. So I will make the weak_ref
constructor private, making enable_weak_ref
a friend. I will put the weak_ref
class inside enable_weak_ref
:
template<typename CRTP>
class enable_weak_ref
public:
class weak_ref /**/ ;
/**/
;
So instead of weak_ref<T>
we have enable_weak_ref<T>::weak_ref
. I think it makes more understandable the use of these classes.
Also, because weak_ref
should not modify the pointer in weak_data_
, I would use std::shared_ptr<T* const>
so it is clear that this pointer is for read-only use.
If you do not want to use std::shared_ptr
, you should create a int*
(counting references), a CRTP**
(which will hold this
or nullptr
) in enable_weak_ref
, and weak_ref
should have a int* const
and a CRTP const* const
(const specifier shows that weak_ref
is linked to only one enable_weak_ref
and can not be changed).
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative toshared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to sayshared_ptr<T const*>
butshared_ptr<T* const>
, because yourweak_ptr
should not modify which instance the pointer points.
â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (inenable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)
â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has ashared_ptr<T*>
, butweak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified inweak_ref
, so it holdsshared_ptr<T* const>
. It is what i meant.
â Julien Vernay
Jan 4 at 14:55
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
I never saw a similar pattern so it was really interesting to understand your code !
First, about the name weak_ref
, it implies that it has the syntax of a reference
, but it is not the case (for instance, operator->
is for pointers). I personnaly named it something like ptr_to_instance
.
Then, it seems the weak_ref
should not be used on its own, without calling enable_weak_ref::get_weak_ref()
. So I will make the weak_ref
constructor private, making enable_weak_ref
a friend. I will put the weak_ref
class inside enable_weak_ref
:
template<typename CRTP>
class enable_weak_ref
public:
class weak_ref /**/ ;
/**/
;
So instead of weak_ref<T>
we have enable_weak_ref<T>::weak_ref
. I think it makes more understandable the use of these classes.
Also, because weak_ref
should not modify the pointer in weak_data_
, I would use std::shared_ptr<T* const>
so it is clear that this pointer is for read-only use.
If you do not want to use std::shared_ptr
, you should create a int*
(counting references), a CRTP**
(which will hold this
or nullptr
) in enable_weak_ref
, and weak_ref
should have a int* const
and a CRTP const* const
(const specifier shows that weak_ref
is linked to only one enable_weak_ref
and can not be changed).
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative toshared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to sayshared_ptr<T const*>
butshared_ptr<T* const>
, because yourweak_ptr
should not modify which instance the pointer points.
â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (inenable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)
â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has ashared_ptr<T*>
, butweak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified inweak_ref
, so it holdsshared_ptr<T* const>
. It is what i meant.
â Julien Vernay
Jan 4 at 14:55
add a comment |Â
up vote
1
down vote
I never saw a similar pattern so it was really interesting to understand your code !
First, about the name weak_ref
, it implies that it has the syntax of a reference
, but it is not the case (for instance, operator->
is for pointers). I personnaly named it something like ptr_to_instance
.
Then, it seems the weak_ref
should not be used on its own, without calling enable_weak_ref::get_weak_ref()
. So I will make the weak_ref
constructor private, making enable_weak_ref
a friend. I will put the weak_ref
class inside enable_weak_ref
:
template<typename CRTP>
class enable_weak_ref
public:
class weak_ref /**/ ;
/**/
;
So instead of weak_ref<T>
we have enable_weak_ref<T>::weak_ref
. I think it makes more understandable the use of these classes.
Also, because weak_ref
should not modify the pointer in weak_data_
, I would use std::shared_ptr<T* const>
so it is clear that this pointer is for read-only use.
If you do not want to use std::shared_ptr
, you should create a int*
(counting references), a CRTP**
(which will hold this
or nullptr
) in enable_weak_ref
, and weak_ref
should have a int* const
and a CRTP const* const
(const specifier shows that weak_ref
is linked to only one enable_weak_ref
and can not be changed).
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative toshared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to sayshared_ptr<T const*>
butshared_ptr<T* const>
, because yourweak_ptr
should not modify which instance the pointer points.
â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (inenable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)
â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has ashared_ptr<T*>
, butweak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified inweak_ref
, so it holdsshared_ptr<T* const>
. It is what i meant.
â Julien Vernay
Jan 4 at 14:55
add a comment |Â
up vote
1
down vote
up vote
1
down vote
I never saw a similar pattern so it was really interesting to understand your code !
First, about the name weak_ref
, it implies that it has the syntax of a reference
, but it is not the case (for instance, operator->
is for pointers). I personnaly named it something like ptr_to_instance
.
Then, it seems the weak_ref
should not be used on its own, without calling enable_weak_ref::get_weak_ref()
. So I will make the weak_ref
constructor private, making enable_weak_ref
a friend. I will put the weak_ref
class inside enable_weak_ref
:
template<typename CRTP>
class enable_weak_ref
public:
class weak_ref /**/ ;
/**/
;
So instead of weak_ref<T>
we have enable_weak_ref<T>::weak_ref
. I think it makes more understandable the use of these classes.
Also, because weak_ref
should not modify the pointer in weak_data_
, I would use std::shared_ptr<T* const>
so it is clear that this pointer is for read-only use.
If you do not want to use std::shared_ptr
, you should create a int*
(counting references), a CRTP**
(which will hold this
or nullptr
) in enable_weak_ref
, and weak_ref
should have a int* const
and a CRTP const* const
(const specifier shows that weak_ref
is linked to only one enable_weak_ref
and can not be changed).
I never saw a similar pattern so it was really interesting to understand your code !
First, about the name weak_ref
, it implies that it has the syntax of a reference
, but it is not the case (for instance, operator->
is for pointers). I personnaly named it something like ptr_to_instance
.
Then, it seems the weak_ref
should not be used on its own, without calling enable_weak_ref::get_weak_ref()
. So I will make the weak_ref
constructor private, making enable_weak_ref
a friend. I will put the weak_ref
class inside enable_weak_ref
:
template<typename CRTP>
class enable_weak_ref
public:
class weak_ref /**/ ;
/**/
;
So instead of weak_ref<T>
we have enable_weak_ref<T>::weak_ref
. I think it makes more understandable the use of these classes.
Also, because weak_ref
should not modify the pointer in weak_data_
, I would use std::shared_ptr<T* const>
so it is clear that this pointer is for read-only use.
If you do not want to use std::shared_ptr
, you should create a int*
(counting references), a CRTP**
(which will hold this
or nullptr
) in enable_weak_ref
, and weak_ref
should have a int* const
and a CRTP const* const
(const specifier shows that weak_ref
is linked to only one enable_weak_ref
and can not be changed).
edited Jan 4 at 14:52
answered Jan 4 at 13:58
Julien Vernay
3138
3138
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative toshared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to sayshared_ptr<T const*>
butshared_ptr<T* const>
, because yourweak_ptr
should not modify which instance the pointer points.
â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (inenable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)
â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has ashared_ptr<T*>
, butweak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified inweak_ref
, so it holdsshared_ptr<T* const>
. It is what i meant.
â Julien Vernay
Jan 4 at 14:55
add a comment |Â
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative toshared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to sayshared_ptr<T const*>
butshared_ptr<T* const>
, because yourweak_ptr
should not modify which instance the pointer points.
â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (inenable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)
â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has ashared_ptr<T*>
, butweak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified inweak_ref
, so it holdsshared_ptr<T* const>
. It is what i meant.
â Julien Vernay
Jan 4 at 14:55
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
Thanks for the review! A few notes: both my problem statement and sample code showcase mutation, I'm not sure where you see the constness requirement. Namespacing weak_ref would just be super-rough api-wise, it's not always going to be inferred. Your alternative to shared_ptr leaves a lot to be desired, it would be much better to pack the ref count and data pointer in a struct. It's also not "that" simple, there's quite a few edge cases to handle.
â Frank
Jan 4 at 14:27
About alternative to
shared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to say shared_ptr<T const*>
but shared_ptr<T* const>
, because your weak_ptr
should not modify which instance the pointer points.â Julien Vernay
Jan 4 at 14:50
About alternative to
shared_ptr
, yes it was just "you may need" not a full implementation. I don't know very much about mutation, but constness as I depicted is not a requirement but just to explicit the uses of the variable. I saw I made a mistake, I didn't want to say shared_ptr<T const*>
but shared_ptr<T* const>
, because your weak_ptr
should not modify which instance the pointer points.â Julien Vernay
Jan 4 at 14:50
But the variable is not const in any meaning of the word. The pointer can be changed (in
enable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)â Frank
Jan 4 at 14:51
But the variable is not const in any meaning of the word. The pointer can be changed (in
enable_weak_ref
's move constructor), and the content pointed to by the pointer can change (as seen in the examples)â Frank
Jan 4 at 14:51
enable_weak_ref
can change where the pointer points, so indeed it has a shared_ptr<T*>
, but weak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified in weak_ref
, so it holds shared_ptr<T* const>
. It is what i meant.â Julien Vernay
Jan 4 at 14:55
enable_weak_ref
can change where the pointer points, so indeed it has a shared_ptr<T*>
, but weak_ref
needs only to know the value of the pointer itself, eventually modifying the dereference. but the pointer itself should not be modified in weak_ref
, so it holds shared_ptr<T* const>
. It is what i meant.â Julien Vernay
Jan 4 at 14:55
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184242%2fa-free-standing-weak-ptr-equivalent-to-handle-lifetime-of-non-shared-callback-ob%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password