Hello all. 

I've attached a small bit of purely "fun" code I came up with last night
demonstrating an implementation of osg::ref_ptr (in the form of
osg::Pointer) that tries to determine, upon attempting to invoke a
method on a null pointer, what kind of object threw the error. It uses a
real nasty hack to do so, but it's still kind of interesting. :)

Basically, if you define OSG_POINTER, the derived class will overload
operator->() and do some error checking. Otherwise, the Pointer class
will just be a tiny "shim" over the real osg::ref_ptr.

Anyways, this is just for informational purposes. *grin*
#include <sstream>
#include <exception>
#include <osg/ref_ptr>
#include <osg/notify>

namespace osg {

// If the user defines OSG_POINTER, use our custom implementation that is a bit
// slower but more verbose. :)
#ifdef OSG_POINTER

// I like the ref_ptr, but I'd like a version that throws an exception when you
// try and call a method on something that is set to 0.
template <typename T>
class Pointer: public osg::ref_ptr<T> {
public:
	Pointer(): osg::ref_ptr<T>() {}
	Pointer(T* ptr): osg::ref_ptr<T>(ptr) {}
        Pointer(const Pointer& rp): osg::ref_ptr<T>(rp) {}

	T* operator->() {
		// The following code is a super-dirty hack that allows us to try and get
		// the class name of the object that the ref_ptr failed on. We do it by
		// attemping to actually create a good one ourselves and invoke className()
		// and libraryName on it.
		if(not osg::ref_ptr<T>::valid()) {
			std::stringstream error;

			error << "You tried to call a method on a null Pointer of type ";

			try {
				osg::ref_ptr<T> t = new T();

				error << t->libraryName() << "::" << t->className();
			}

			catch(std::bad_alloc) {
				error << "UNKNOWN! (std::bad_alloc)";
			}

			error << 
				". This probably means you forgot to actually create the "
				"object, and just have the Pointer around. Unfortunately, I "
				"can't actually determine WHERE the error took place."
			;

			osg::notify(osg::FATAL) << error.str() << std::endl;

			// This is my own exception class; won't work in this context.
			// throw Exception(error.str().c_str());
			throw std::exception();
		}

		else return osg::ref_ptr<T>::operator->();
	}
};

// Otherwise, just use a lightweight wrapper around the real osg::ref_ptr.
#else

template <typename T>
class Pointer: public osg::ref_ptr<T> {
public:
	Pointer(): osg::ref_ptr<T>() {}
	Pointer(T* ptr): osg::ref_ptr<T>(ptr) {}
        Pointer(const Pointer& rp): osg::ref_ptr<T>(rp) {}
};

#endif

}

#endif
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to