12

If I defined a class:

class Blah {};

How can I:

std::string const className = /* What do I need to do here? */;
assert( className == "Blah" );

I dont think typeid().name() is a good idea since it's compiler implementation specific. Is there anything provided by the C++ standard or Boost?

Note: If the class were inherited from Qt's QObject, I could easily use QMetaObject::className() to get the class name.

Community
  • 1
  • 1
sivabudh
  • 31,807
  • 63
  • 162
  • 228

6 Answers6

10

Like this:

class Blah { static std::string const className() { return "Blah"; }};

std::string const name = Blah::className();
assert(name == "Blah");

Or this:

class Blah {};

template < typename T > struct name;
template < > struct name<Blah> { static std::string value() { return "Blah"; }};

std::string const classname = name<Blah>::value();
assert(classname == "Blah");

Fancier:

#define DECLARE_NAMED_CLASS( Name ) \
struct Name;\
template < > struct name<Name> { static std::string value() { return #Name; }};\
struct Name

DECLARE_NAMED_CLASS(Blah) {};
std::string const className = name<Blah>::value();
...

Or this:

class Blah : QObject { Q_OBJECT };

Or this:... Or this: ...

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • 6
    Another solution would be typeid () + demangle. Otherwise, how could you handle namespaces etc.? –  Dec 16 '10 at 23:00
  • The first case is the only serious one. It's readable, easy to maintain and to use. The second overcomplicates a simple problem. Maybe you'd rather utilize a REST api to call a webservice instead? The third one is is considered as bad habit. When it comes to good design, the preprocessor is the worst and the last thing you should utilize. The only few reasonable use cases for preprocessors i can think of is pragma once. – nali Dec 05 '17 at 22:25
3

Testing a class by looking at it's name sounds awfully like a Java style approach to me, and in C++, you should be wary of trying to apply the same patterns! A better way would be to use something like boost::type_traits, and may be is_same, with the real class name.

rstackhouse
  • 2,238
  • 24
  • 28
Nim
  • 33,299
  • 2
  • 62
  • 101
1

I don't think there's any non-compiler specific solution to such problem that does not involve plenty of macros in the class declaration (actually if I understood correctly the QT documentation the string you get with objectName is actually assigned "by hand", I think with code created by moc).

On the other hand, in general to check if the class of an object is one you don't want you shouldn't do a string comparison, but instead make a typeid comparison.

assert(typeid(YourObject)==typeid(Blah));

But probably you should explain better what you're trying to achieve.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
1

I think a dynamic_cast may be what you are looking for. It does not give you the name of the class, but it fails in the way you would like your assertion to fail, except that subclasses of Blah will not be caught.

Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
1

I dont think typeid().name() is a good idea since it's compiler implementation specific.

Yes, standard doesn't require from implementation to use any specific naming, so it may change even for the same compiler.

Is there anything provided by the C++ standard or Boost?

There are no standard facilities that would return class name in some canonic form.

Flow
  • 23,572
  • 15
  • 99
  • 156
Gene Bushuyev
  • 5,512
  • 20
  • 19
1

The QObject->metaObject() method is valid for Qt except the QGraphicsItem based classes that not inherit from QObject...

MasterMito
  • 11
  • 5