From 99fd6ed93a60701a1ab03b9be4fdd5adb2c19d75 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 3 Oct 2008 09:55:20 +0000 Subject: [PATCH] From Neil Groves, "Frequently I would like code that has a signature like: void foo(osg::ref_ptr node) to work for osg::ref_ptr, osg::ref_ptr 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." --- include/osg/ref_ptr | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/include/osg/ref_ptr b/include/osg/ref_ptr index 00b768833..a18155e16 100644 --- a/include/osg/ref_ptr +++ b/include/osg/ref_ptr @@ -26,19 +26,19 @@ class ref_ptr ref_ptr() : _ptr(0) {} ref_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); } ref_ptr(const ref_ptr& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); } + template ref_ptr(const ref_ptr& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); } ~ref_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; } ref_ptr& operator = (const ref_ptr& rp) { - if (_ptr==rp._ptr) return *this; - 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(); + assign(rp); + return *this; + } + + template ref_ptr& operator = (const ref_ptr& rp) + { + assign(rp); return *this; } @@ -78,6 +78,21 @@ class ref_ptr void swap(ref_ptr& rp) { T* tmp=_ptr; _ptr=rp._ptr; rp._ptr=tmp; } private: + + template void assign(const ref_ptr& 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 friend class ref_ptr; + T* _ptr; };