 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
T. Lovset Guest
|
Posted: Fri Jul 16, 2004 11:23 am Post subject: smart pointers shortcomings question/repair |
|
|
Hi, everyone.
Having used my own smart pointers for years, I find it strange that
both boost::shared_ptr and Loki::SmartPtr still lack an obvious
feature. One of the goals for smart pointers is that they should mimic
the syntax of regular pointers as closely as possible, which is
important when converting from regular to smart pointers. Recent
updates to boost::shared_ptr even safely allows the syntax: if (p) ...
Why then, is the ability to initialize and assign to NULL still left
out?
For boost::shared_ptr, it can be achieved simply by:
template <class T> class shared_ptr {
struct null_tag {};
public:
shared_ptr(null_tag* = NULL) : px(0), pn() {}
shared_ptr& operator=(null_tag*) { reset(); return *this; }
...
which allows code like:
boost::shared_ptr<int> p = NULL;
...
p = NULL;
---
A second, but more serious problem with current implementations of
smart pointers is illustrated in the following:
class Widget {
public:
Widget(Danger* d) : m_danger(d) {}
...
private:
Danger* m_danger;
If we change the attribute m_danger to type boost::shared_ptr<Danger>,
but fail to observe that the constructor takes a raw Danger pointer,
this code still compiles fine, but has now become a time-bomb. The
correct code would be to have a const boost::shared_ptr<Danger>& as
ctor-argument. However, shared_ptr should rather have disallowed
initialization directly from a regular pointer.
The way I have overcome this problem, is by wrapping a handle class
around the raw pointers:
// this class could be more sophisticated...
template <typename T> class new1_handle {
public:
explicit new1_handle(T* p) : px(p) {}
T* release() const { return px; }
private:
T* px;
};
template <typename T>
inline new1_handle<T> make_new1_handle(T* p) {
return new1_handle<T>(p);
}
Adding a dreaded macro makes it easier for real-life usage:
#define new1(X) make_new1_handle(new X)
// example
smart_ptr<Widget> w = new1( Widget(...) );
The ctor is then something like:
template <typename U> smart_ptr(const new1_handle<U>& m)
: px(m.release()) {}
I hope these ideas will emerge in the standard smart pointer
implementations soon. For me, they are simply too important to be left
out.
Regards, TL.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joe Gottman Guest
|
Posted: Sat Jul 17, 2004 10:17 am Post subject: Re: smart pointers shortcomings question/repair |
|
|
"T. Lovset" <tylo (AT) start (DOT) no> wrote
| Quote: | Hi, everyone.
Having used my own smart pointers for years, I find it strange that
both boost::shared_ptr and Loki::SmartPtr still lack an obvious
feature. One of the goals for smart pointers is that they should mimic
the syntax of regular pointers as closely as possible, which is
important when converting from regular to smart pointers. Recent
updates to boost::shared_ptr even safely allows the syntax: if (p) ...
Why then, is the ability to initialize and assign to NULL still left
out?
For boost::shared_ptr, it can be achieved simply by:
template <class T> class shared_ptr {
struct null_tag {};
public:
shared_ptr(null_tag* = NULL) : px(0), pn() {}
shared_ptr& operator=(null_tag*) { reset(); return *this; }
...
which allows code like:
boost::shared_ptr<int> p = NULL;
...
p = NULL;
|
Unfortunately this won't work. shared_ptr also has a constructor
template <class U> shared_ptr(U *pu);
When you later say
shared_ptr<int> p(NULL);
the compiler won't know which constructor to call; NULL can be converted to
an int* or to a null_tag *. There is a proposal now before the standard
committee which would fix this problem by creating a special value called
nullptr, which can be cast to any pointer type, but not to int, bool, etc.
The value nullptr would have a special type, called nullptr_t. If this
proposal is added, we could overload shared_ptr's constructor to take a
nullptr_t parameter. Here is a link to the proposal.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1601.pdf
Joe Gottman
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
T. Lovset Guest
|
Posted: Tue Aug 03, 2004 11:24 am Post subject: Re: smart pointers shortcomings question/repair |
|
|
"Joe Gottman" <jgottman (AT) carolina (DOT) rr.com> wrote
| Quote: | Why then, is the ability to initialize and assign to NULL still left
out?
For boost::shared_ptr, it can be achieved simply by:
template <class T> class shared_ptr {
struct null_tag {};
public:
shared_ptr(null_tag* = NULL) : px(0), pn() {}
shared_ptr& operator=(null_tag*) { reset(); return *this; }
...
which allows code like:
boost::shared_ptr<int> p = NULL;
...
p = NULL;
Unfortunately this won't work. shared_ptr also has a constructor
template <class U> shared_ptr(U *pu);
When you later say
shared_ptr<int> p(NULL);
the compiler won't know which constructor to call; NULL can be converted to
an int* or to a null_tag *.
|
Thanks Joe, you are right, but in the second part of my post I meant
to suggest to use:
template <class U> shared_ptr(const new1_handle<U>& h);
INSTEAD of
explicit template <class U> shared_ptr(U *pu);
It then will work, and this will give an important safety benefit (see
post) in addition to a more intuitive usage and ease when switching
back and forth between raw and smart pointers:
shared_ptr<Widget> mySmartPtr = new1( Widget(name, type) );
mySmartPtr = NULL
mySmartPtr = new1( Widget(name, type) );
rather than:
shared_ptr<Widget> mySmartPtr( new Widget(name, type) );
mySmartPtr.reset();
mySmartPtr.reset( new Widget(name, type) );
This also imply using:
template <class U> operator=(new1_handle<U>& h);
instead of (or maybe here in addition to)
template <class U> reset(U *pu);
PS: I know the macro "new1" will not be accepted in an implementaton,
but you can do without it. Changing the name of function
make_new1_handle() to rawptr() or something similar, may improve
readability. This will give the safe and explicit syntax:
mySmartPtr = rawptr( new Widget() );
| Quote: | There is a proposal now before the standard
committee which would fix this problem by creating a special value called
nullptr, which can be cast to any pointer type, but not to int, bool, etc.
The value nullptr would have a special type, called nullptr_t. If this
proposal is added, we could overload shared_ptr's constructor to take a
nullptr_t parameter. Here is a link to the proposal.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1601.pdf
Yes, thanks. This would also solve the first issue in my post, |
although sometime in the future.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|