From: stephan b. <st...@wa...> - 2003-10-13 19:11:38
|
This should work for just about any project. i'll admit it bloats the glo= bal=20 space a bit (one extra helper class per registered class), but it's very=20 generic and easy to use... namespace { // anon ns important for linking /** A slimmer, more general-purposes class than classloader_registerer<>. It MUST be specialized to work. */ template <class T> struct class_name {=20 class_name(){} ~class_name(){} operator const char * () const {=20 assert( 0 /* this class_name<> is unspecialized! = */ ); return "error::class_name<unspecialized>"; // a more sane default would be typeid(T).name() } // static const char * classname =3D 0; // ^^^^^ we can't initalized a non-integral type this way= :( static const char * name() { assert( 0 /* this class_name<> is unspecialized! = */ ); return "error::class_name<unspecialized>"; } }; } // call this from outside a namespace to register a class_name<Type> #define CLASS_NAME(Type) \ =09namespace {\ template <> struct class_name<Type> {\ class_name(){}; ~class_name(){}; \ =09 static const char * name() {return # Type; }\ operator const char * () const { return this->name(); }\ };} Usage: CLASS_NAME(MyClass); COUT << "name =3D " << class_name<MyClass>() << std::endl; COUT << "name =3D " << class_name<MyClass>::name() << std::endl; Caveat: typedef std::vector<int> FooType; CLASS_NAME(FooType); // will use "FooType" :( Maybe that's useful in some contexts, but i'm not sure if it's a feature = or a=20 bug. It's not name-collision-proof, but it is the type passed to=20 class_name<T> which is important, anyway. This would be more efficient to implement as global funcs, but func templ= ates=20 can't be specialized, AFAIR. --=20 ----- st...@wa... http://qub.sourceforge.net http://libfunutil.sourceforge.net =20 http://toc.sourceforge.net http://countermoves.sourceforge.net http://stephan.rootonfire.org et al. |