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/