views:

146

answers:

6

I would like my classes to be identified each type by an unique hash code. But I don't want these hashed to be generated every time a method, eg. int GetHashCode(), is invoked during runtime. I'd like to use already generated constants and I was hoping there is a way to make the compiler do some come computing and set these constants. Can it be done using templates? Could you give me some example, if it is possible.

UPDATE:

Thanks to kriss' comment I realized my question should go like this: How to do the type checking with the lowest runtime cost possible?

I'd like to check a pointer to an object against a class type. Just the classes I implement in my libs, so I was thinking of some custom hashing, thus the original question. I did consider using typeid but I am unaware of the runtime cost of using it. I made an assumption that since typeid produces a type_info class that would be more consuming than simple comparision of unique int values.

+4  A: 

You can do it with boost.MPL.

Will
I do not want to use boost, sorry. I should have mentioned this in my question.
AOI Karasu
+2  A: 

I would go simple route:

  • For classes that would be static property - so just pick a number for each class.
  • For instances - just use the address.
Nikolai N Fetissov
I handle instances checking as you say (except some cases), but picking a number for each class is not an option for me. I'm developing 3 libs that can go solo or cooperate and don't want to check each time I create a class whether a number is unique across all 3 libs.
AOI Karasu
There's always Perl.
Nikolai N Fetissov
+1  A: 

Static const's are evaluated at compile time - which is pretty much the basis for metaprogramming at large. Moreover, type_info::hash_code is particularly adapted for your needs, so try -

class MyClass
{
static const size_t TypeHashCode = typeid(MyClass).hash_code();
...
}

(I'm not around a compiler right now, so this may take some refining. Will try and recheck tomorrow)

EDIT: indeed, it is not only MS specific but also added only in VS2010 - but hey, at least MS agrees this is a valid need. If you don't allow both VS2010 and boost in your code - you're pretty much left with the standard compliant facilities: typeid or dynamic_cast. They do incur some overhead, but I'd take extra care to verify this overhead is indeed a worthy battle. (my money goes to - not.)

Ofek Shilon
Warning: typeid::hash_code() is an MS-specific extension.
Drew Hall
error C2039: 'hash_code' : is not a member of 'type_info'
AOI Karasu
A: 

All such classes share something common. Then why not add a symbolic constant in a common enum for each one, you'll leave the enum give values for you, it's easier than giving explicit constants (you still have to declare each class in the enum).

kriss
Using an enum is my current solution but I want to change it since to fit my needs such enum should extendable outside my lib.
AOI Karasu
A: 
template<class T>
struct provide_hash_code_for_class
{
  public:
    static uintptr_t GetHashCode()
    {
      return(reinterpret_cast<uintptr_t>(&unused));
    }
  private:
    static void *unused;
};

template<class T>
void *provide_hash_code_for_class<T>::unused;

class MyClass : public provide_hash_code_for_class<MyClass>
{
};

int main()
{
  std::cout << std::hex << MyClass::GetHashCode() << std::endl;
  std::cout << std::hex << MyClass().GetHashCode() << std::endl;
  return(0);
}

Please be aware that hash codes will change between runs so you can't rely on them for example for interprocess communication.

Tomek
Classes that derive from MyClass have the same hash code as the base, which is not acceptable. Using provide_hash_code_for_class<MyDerivedClass> results in compilation error C2385: ambiguous access of 'GetHashCode'.
AOI Karasu
That's a good point. You probably can disambiguate symbol using 'using provide_hash_code_for_class<MyDerivedClass>::GetHashCode' in the class your are writing but this is too much typing... And I guess trait type class is out of the question as you probably do not want to change the interface?
Tomek
A: 

building on the simple route route by Nikolai N Fetissov:

  • For classes that would be static property - use the address of a function cast to an intptr_t to give a unique yet compiled-in value.
  • For instances - just use the address.
Will