Request for consideration for my weak_ptr class

Hello Boost developers <Class definition below> I understand there would be a collision with boost::weak_ptr, which is used for special scenarios with shared_ptr as I understand. A fair comment would be that this class actually does nothing, that a normal pointer would do and this is true. However, I find it extremely useful, and would like it considered as an addition to boost. It allows my code to be free of the * pointer notation. All pointers look the same, ie shared_ptr<Foo>, scoped_ptr<Foo>, weak_ptr<Foo> It throws an exception if it has been default constructed or set to 0, this could probably be a debug only behaviour for efficiency, but i leave it in release code. It can be used in many places a reference would be used. It includes constructors for many smart pointer types and from a reference to the class pointed to. using namespace std; struct IFoo { }; struct Foo : IFoo { }; vector<Foo> foos; BOOST_FOREACH(weak_ptr<Foo> f,foos) { //do something with f-> } vector< weak_ptr<IFoo> > weakfoos; std::copy(foos.begin(),foos.end(),back_inserter(weakfoos)); In the above code, if vector<Foo> foos was changed to vector< shared_ptr<Foo> > the code will still work perfectly with out change. I find this really useful because often small structs become polymorphic classes (requiring shared_ptr) as code evolves. The vector example is the best, but even when returning a pointer to something like this it is good: struct Bar {}; struct Foo { Bar mBar; weak_ptr<Bar> bar() const { return mBar; } }; if Bar mBar becomes scoped_ptr<Bar> mBar, the accessor still compiles. //Definition starts here namespace alex { class null_weak_ptr_exception : public std::runtime_error { public: null_weak_ptr_exception() : std::runtime_error("null_weak_ptr_exception : dereferencing null pointer") {} }; template <typename T> class weak_ptr { private: T * p; public: weak_ptr() : p(0) {} weak_ptr(weak_ptr const & x) : p(x.p) {} weak_ptr & operator=(weak_ptr const & x) { p = x.p; return *this; } weak_ptr(T * p) : p(p) {} weak_ptr(T & ref) : p(&ref) {} template<class Y> weak_ptr(const alex::weak_ptr<Y> & y) : p(y.get()) { } template<class Y> weak_ptr(const std::auto_ptr<Y> & y) : p(y.get()) { } template<class Y> weak_ptr(const boost::shared_ptr<Y> & y) : p(y.get()) { } template<class Y> weak_ptr(const boost::scoped_ptr<Y> & y) : p(y.get()) { } template<class Y> weak_ptr(const alex::aggregate_ptr<Y> & y) : p(y.get()) { } T & operator*() const { if (!p) throw null_weak_ptr_exception(); return *p; } T * operator->() const { if (!p) throw null_weak_ptr_exception(); return p; } T * get() const { return p; } }; template <typename T> bool operator == (const weak_ptr<T> & x,const weak_ptr<T> & y) { return x.get() == y.get(); } }

Alex Burton wrote:
I understand there would be a collision with boost::weak_ptr, which is used for special scenarios with shared_ptr as I understand.
Hm. checked_ptr, standard_ptr, regular_ptr, simple_ptr or just raw_ptr might be better names, to avoid collisions? (The concept of a weak pointer or reference is quite common when used in garbage collection, as with boost::shared_ptr, so IMHO I would avoid that in general for non-gc pointer types.)
A fair comment would be that this class actually does nothing, that a normal pointer would do and this is true. However, I find it extremely useful, and would like it considered as an addition to boost.
Good initiative. However, there seems to be some orthogonal concepts baked in here, and everyone might not want all of them at the same time, even if each one is useful on their own. Perhaps each concept could be split up (via policy classes) so that one could define checks for any pointer?
It allows my code to be free of the * pointer notation. All pointers look the same, ie shared_ptr<Foo>, scoped_ptr<Foo>, weak_ptr<Foo>
Why is that desirable?
It throws an exception if it has been default constructed or set to 0, this could probably be a debug only behaviour for efficiency, but i leave it in release code.
I find the notion of a null ptr useful. How about just checking that in operator * and -> as other boost::ptr's. Unless actually do want a nonnull_ptr, but that should be optional. (boost::ahared_ptr's can be
It can be used in many places a reference would be used.
I don't get this one. It's not a smart reference, a smart pointer?
It includes constructors for many smart pointer types and from a reference to the class pointed to.
Useful. However, you might want to consider a unqualified get_pointer() call to allow for any smart pointer (including my secret one that I won't show you :-). Also, less constructors. (as for get_pointer(), I believe boost::bind and others uses it to get the raw-pointer from any type, including references)
using namespace std;
struct IFoo { };
struct Foo : IFoo { };
vector<Foo> foos;
BOOST_FOREACH(weak_ptr<Foo> f,foos) { //do something with f-> }
vector< weak_ptr<IFoo> > weakfoos; std::copy(foos.begin(),foos.end(),back_inserter(weakfoos));
In the above code, if vector<Foo> foos was changed to vector< shared_ptr<Foo> > the code will still work perfectly with out change.
I find this really useful because often small structs become polymorphic classes (requiring shared_ptr) as code evolves.
Yup. I see where that could be useful. OTOH, the for_each could use an indirect_iterator-range instead, to iterate over IFoo& instead. Cheers, /Marcus
participants (2)
-
Alex Burton
-
Marcus Lindblom