1

I want to use passed template parameter as string. Is it possible?

T is class, what do i need to change to get that code work?

void registerClass(const std::string &name, Handler *handler);

template<class T>
void registerClass() {
   registerClass( "get T as string", new DefaultHandler<T>());
}
K-ballo
  • 80,396
  • 20
  • 159
  • 169
kravemir
  • 10,636
  • 17
  • 64
  • 111
  • 1
    `register` is a C++ keyword, you can't use it as an identifier name. – K-ballo Oct 12 '11 at 19:45
  • yep mistake, sorry. I've edited it, it's not the real code :) – kravemir Oct 12 '11 at 19:46
  • 1
    Do you really need the type as a string, or just a different string for each type to use as some kind of dictionary key? – K-ballo Oct 12 '11 at 19:48
  • I need it as string. Because i'll access it with that class name. – kravemir Oct 12 '11 at 19:51
  • 2
    Look at [this](http://stackoverflow.com/questions/7691697/). Read the answer, it's a good pattern. And if you want demangle the names use `abi::__cxa_demangle()` _(gcc)_ – masoud Oct 12 '11 at 20:49

4 Answers4

6

The closest you can get to get a type as a string is with typeid( T )->name(). However, there is no standarization for type names, so you can't trust in getting a valid name from it. A standard compliant implementation may very well return empty strings for all type names.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • `typeid` is an operator, not a function, so it doesn't live in the `std::` namespace. And it returns a pointer so you need to use `->` instead of `.`. – Mark Ransom Oct 12 '11 at 19:49
  • Yes, there's no standartization, it generates names with numbers. So, i'm looking for any other way if possible without declaration of static method inside of each class that i use there. – kravemir Oct 12 '11 at 19:49
  • 1
    @MiroK: If you really need the class names, then you are out of luck. The best you could do is provide a function `get_type_name` and overload it for each of the types you want to support to return the type name. – K-ballo Oct 12 '11 at 20:13
2

You can use typeid(T) to obtain a std::type_info structure to describe the type. This structure, in turn, has a name() member that should give you the name.

template<class T>
void fooClass() {
   foo( "get " + std::string( typeid(T).name() ) +" as string", new DefaultHandler<T>());
}
Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • 1
    You will need a function to clean up the name. For example, GCC prefixes an arbitrary number. – Ben Jackson Oct 12 '11 at 19:51
  • 2
    On GCC you can put the `typeid` through `abi::__cxa_demangle()` to get a relatively readable type name, but that's not portable. – Kerrek SB Oct 12 '11 at 20:13
2

Does it have to be a template parameter? Maybe the C processor can help:

void registerClass(const std::string &name, Handler *handler);

#define REGISTER_CLASS(t) (registerClass( #t, new DefaultHandler<t>()))

void RegisterMyClasses() {  
  REGISTER_CLASS(int);
  REGISTER_CLASS(Foo);
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
1

C++ doesn't have reflection like C# or Java does. This is not a mistake. Reflection has been considered more than once, and intentionally left out of the language.

HOWEVER, you can get something close to your design. You will have to do a lot of work yourself. You will have to, essentially, implement reflection in a language that intentionally doesn't provide it.

Your current design is close. If I were to implement reflection the way you appear to be going I would do:

class Reflection_registry {
    std::map<std::string, Handler*> registry_;

public:
    void registerClass(const std::string& name, Handler* handler) {
        registry_[name] = handler;
    }

    Handler* getHandlerForClass(std::string& name) {
        std::map<std::string, Handler*>::iterator itor = registry_.find(name);
        return itor == registry_.end() ? NULL : itor->second;
    }
}

The thing is that you will be responsible for coming up with the relevant names, by hand, and keeping them up to date. As others have suggested, you can use typeid and std::type_infos to generate the names -- that's pretty much the kind of thing std::type_info was designed for.

Max Lybbert
  • 19,717
  • 4
  • 46
  • 69