views:

97

answers:

4
+1  Q: 

Class name macro

Possible Duplicate:
CLASS macro in C++

Hello, are there any ways to get name of class with macro like _FUNCTION_ for function name? The only ideas I have is inheriting some base class with pure virtual toString and define the names by hands eash time. Thanks.

A: 

Use a macro to define the class:

#define CLASS_WITH_NAME(name)  name { const char * __NAME = #name;

class CLASS_WITH_NAME(class_name) // No "{" here!

Ugly hack but the best I can think of.

Aaron Digulla
Yuck, that's ugly. I like it.
Patrick
Wow, really crazy :D Thanks.
Ockonal
Quite hard to use inheriting with that macro...
tibur
@tibur: Add additional options to the macro if you need inhertiance.
Aaron Digulla
@Ock: Gross, please don't actually do this. `__NAME` is reserved, by the way. Just use `typeid(T).name()` and move on; any implementation you care about gives a nice result.
GMan
For what it's worth, it would be better written as (yes I'm aware this will appear squished): `#define CLASS_WITH_NAME(name) namespace detail { class class_name_base_detail_##name { public: const char* _class_name_ = #name; }; protected: class_name_base_detail_##name(){} ~class_name_base_detail_##name(){} } class name , public detail::class_name_base_detail_##name` so its interference is minimal. Use it like `CLASS_WITH_NAME(foo) { /* normal */ };` or `CLASS_WITH_NAME(bar) , public base, private mixin { /* normal */ };`, much better. But don't actually use it.
GMan
@GMan: Make it stop! @Aaron: I'm sorry, but this has so many problems I need to downvote. In particular, you can't declare a nonstatic `const char*` like that.
Potatoswatter
@Potato: Oh, pretend I made my `_class_name_` thing static... :P
GMan
+2  A: 

Easiest is probably (to define a macro) calling some function to derive the class name from __FUNCTION__ (or __PRETTY_FUNCTION__ for GCC, or maybe even __FILE__).

Michel de Ruiter
+1 If you put each class in a different file then __FILE__ is your best (cross-compiler) option.
Aaron Digulla
Yes, __PRETTY_FUNCTION__ contains the class name for GCC, but I can't see any application for the more-portable __FUNCTION__ and __FILE__...?
Tony
@Aaron: oh yikes... yeah... yuck... :-)
Tony
@Tony: for Microsoft Visual Studio, `__FUNCTION__` contains the class name (as `__PRETTY_FUNCTION__` probably does for GCC).
Michel de Ruiter
@Michel: oh I see... thanks for the explanation
Tony
+6  A: 

It depends what exactly is the context. A rough equivalent to get the implementation defined internal name of the class could be to use typeid operator as shown. Note that the output is implementation defined.

typeid(yourclass).name()

Chubsdad
+1, though RTTI is only required by the Standard for classes with virtual functions.
Tony
@Tony: Huh? §5.2.8/3: "When typeid is applied to an expression other than an lvalue of a polymorphic class type, the result refers to a type_info object representing the static type of the expression. Lvalue-to-rvalue (4.1), array- to-pointer (4.2), and function-to-pointer (4.3) conversions are not applied to the expression." That covers several bases, and specifically excludes classes with virtual functions as the very first condition.
Potatoswatter
@Potatoswatter: fascinating! I see that's in the Draft Standard, did it make it into the final? Many other reference (e.g. http://www.codingunit.com/cplusplus-tutorial-typecasting-part-2-rtti-dynamic_cast-typeid-and-type_info, http://www.codeguru.com/cpp/tic/tic0270.shtml, http://en.wikipedia.org/wiki/Run-time_type_information) are very explicit about RTTI being only available for dynamic types, and I'm sure I've read that in multiple places over many years, though perhaps that predates C++03? Anyone who knows - please chip in....
Tony
@Tony: I think what they mean is that `typeid` on a non-polymorphic object isn't dynamic. So it's not properly RTTI, it's just returning a static global object of type `type_info`. That doesn't matter for this application since we're passing a typename, not an object: it will *never* be dynamic.
Potatoswatter
+1  A: 

Another alternate could be as follows, though it has it's own downside

map<string, string> classdescrmap;     // store association system name, development name

struct A{
    A(){
        classdescrmap[typeid(*this).name()] = "A";
    }
};

struct B : A{
    B(){
        classdescrmap[typeid(*this).name()] = "B";
    }
};

string getname(string const &key){
    return classdescrmap[key];
}

int main(){
    B b;
    cout << getname(typeid(b).name());
}
Chubsdad
If you do this, you should use the `type_info` objects themselves for the map's key. (I think `type_info` has some mechanism precisely for `std::less` to work on it.) The strings don't need to be unique, the `type_info` objects need. Also, comparing `type_info` objects might be faster than comparing strings.
sbi