2

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.

Community
  • 1
  • 1
Max Frai
  • 61,946
  • 78
  • 197
  • 306

4 Answers4

8

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
  • 24,777
  • 4
  • 73
  • 129
  • +1, though RTTI is only required by the Standard for classes with virtual functions. – Tony Delroy Aug 25 '10 at 08:31
  • 1
    @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 Aug 25 '10 at 08:42
  • @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 Delroy Aug 25 '10 at 09:23
  • 1
    @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 Aug 25 '10 at 10:20
6

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
  • 7,131
  • 5
  • 49
  • 74
2

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
  • 321,842
  • 108
  • 597
  • 820
  • 2
    Yuck, that's ugly. I like it. – Patrick Aug 25 '10 at 07:58
  • 3
    Quite hard to use inheriting with that macro... – tibur Aug 25 '10 at 08:01
  • @tibur: Add additional options to the macro if you need inhertiance. – Aaron Digulla Aug 25 '10 at 08:17
  • 5
    @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. – GManNickG Aug 25 '10 at 08:21
  • 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. – GManNickG Aug 25 '10 at 08:26
  • @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 Aug 25 '10 at 08:38
  • @Potato: Oh, pretend I made my `_class_name_` thing static... :P – GManNickG Aug 25 '10 at 08:52
  • you could go the microsoft way and do a typedef macro, i'm pretty sure their DECLARE_DYNAMIC or something like it had some weird typedef where they used a generic name like "ThisClass" or something, check the MFC headers for details on that one. Not going to try to reduplicate it here since it still smells, you wont find things like that in any sane framework. (of course if you are rich you are allowed to be insane). – osirisgothra Jan 27 '14 at 15:42
2

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
  • 24,777
  • 4
  • 73
  • 129
  • 1
    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 Aug 25 '10 at 10:25