views:

107

answers:

3

After reading C++ compile-time string hashing with Boost.MPL, and considering a problem I have, the following came to my mind.

I have the base class:

template<class Command>
class Base {
  typedef Command CommandType;
}

It is supposed to be a utility base class for the Commands classes, so they don't need to typedef and declare some members on their own, they would simply inherit from Base with the types they refer to. So they can be used like this:

class CommandInstantiatorA : public Base<CommandA>
{
public:
   static std::string GetID() { return "CommandInstantiatorA "; }
}

However, there is this other method (GetID) which I couldnt "templatize" which returns an unique ID throught the application. I would like to be able to hash the type passed to the class Base, so the other classes would only need to specify the type. Something like this:

template <class Base>
class Base {
   typedef boost::hash_value(TO_STRING(Base)) ID; //should also be read as: typedef boost::hash_value("CommandA") ID;
   ...
}

Is there such a macro (TO_STRING) that would yield the result "CommandA" in the last example. Is there anything in Boost.MPL that can do this?

+6  A: 

Not in boost but it's just part of C++ so I hope it'll do - maybe you could consider using RTTI - for example like this http://en.wikipedia.org/wiki/Typeid

int main () {
Person person;
Employee employee;
Person *ptr = &employee;
// The string returned by typeid::name is implementation-defined
std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)
std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
std::cout << typeid(ptr).name() << std::endl;      // Person * (statically known at compile-time)
std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time
                                                   //           because it is the dereference of a
                                                  //           pointer to a  polymorphic class)
}
RnR
I would point out that RTTI is available ONLY on class with at least 1 virtual function. Not hard to engineer, but frustrating when it doesn't work and you don't know why. see: http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI and http://www.cplusplus.com/reference/std/typeinfo/type_info/
KitsuneYMG
Another point, typeid can be applied directly to a type. It doesn't have to be an instance. e.g. typeid(Base).name() could replace TO_STRING in you example
KitsuneYMG
A: 

The preprocessor (i.e. macros) have a stringizing operator that can wrap any token in double quote marks. This can't do what you want, at least as written, because it'll stringize the literal token "Base", and not the substituted-in template parameter.

DrPizza
+1  A: 

You can use preprocessor stringification - this probably does not solve everything but you can get the string:

#include <iostream>
using namespace std;

#define ToString(x) #x
struct C { static const string id; };

const string C::id = ToString(C_ID);

int main()
{
    C c;
    cout << c.id << endl;
}

Prints:

C_ID
stefanB