From Neil Groves, "Frequently I would like code that has a signature like: void foo(osg::ref_ptr<osg::Node> node) to work for osg::ref_ptr<osg::Group>, osg::ref_ptr<osg::Geode> etc. The behaviour of osg::ref_ptr does not mimic the behaviour of a raw pointer in this regard.

To facilitate this possibility I have added a template copy constructor and a template assignment operator. These work for safe conversions like those in my previous example, but fail as desired for non-safe conversions since the template instantiation fails during the raw pointer copy/assignment.

The lack of this facility has appreciably handicapped development of generic algorithms applied to the scene graph, and I believe that this alteration will be welcomed by most of the community. If there are issues with antiquated compilers not supporting template member functions then perhaps a small piece of conditional compilation is in order.

I have made the change using the latest release version (2.6) as the base. The full file is attached.

I have not tested building the osg wrappers and the script binding code. I have tested the legal and illegal conversions of both copying and assignment to ensure that behave as expected on MSVC7.1, MSVC8, MSVC9, GCC 4.3."
This commit is contained in:
Robert Osfield 2008-10-03 09:55:20 +00:00
parent 830bb21a32
commit 99fd6ed93a

View File

@ -26,19 +26,19 @@ class ref_ptr
ref_ptr() : _ptr(0) {} ref_ptr() : _ptr(0) {}
ref_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); } ref_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); }
ref_ptr(const ref_ptr& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); } ref_ptr(const ref_ptr& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); }
template<class Other> ref_ptr(const ref_ptr<Other>& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); }
~ref_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; } ~ref_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; }
ref_ptr& operator = (const ref_ptr& rp) ref_ptr& operator = (const ref_ptr& rp)
{ {
if (_ptr==rp._ptr) return *this; assign(rp);
T* tmp_ptr = _ptr; return *this;
_ptr = rp._ptr; }
if (_ptr) _ptr->ref();
// unref second to prevent any deletion of any object which might template<class Other> ref_ptr& operator = (const ref_ptr<Other>& rp)
// be referenced by the other object. i.e rp is child of the {
// original _ptr. assign(rp);
if (tmp_ptr) tmp_ptr->unref();
return *this; return *this;
} }
@ -78,6 +78,21 @@ class ref_ptr
void swap(ref_ptr& rp) { T* tmp=_ptr; _ptr=rp._ptr; rp._ptr=tmp; } void swap(ref_ptr& rp) { T* tmp=_ptr; _ptr=rp._ptr; rp._ptr=tmp; }
private: private:
template<class Other> void assign(const ref_ptr<Other>& rp)
{
if (_ptr==rp._ptr) return;
T* tmp_ptr = _ptr;
_ptr = rp._ptr;
if (_ptr) _ptr->ref();
// unref second to prevent any deletion of any object which might
// be referenced by the other object. i.e rp is child of the
// original _ptr.
if (tmp_ptr) tmp_ptr->unref();
}
template<class Other> friend class ref_ptr;
T* _ptr; T* _ptr;
}; };