javaLover
javaLover

Reputation: 6425

get int Id for each class, called using Class name & its object

I have many classes, B1 B2 ... derived from the same class named A.

I want to create a function

getId<B1>() , getId<B2>() , ...

that return unique int for each class and have result that consistent with

get_id(new B1()) ,  get_id(new B2())    .... 

In other words,

getId<Bi>() == get_id(new Bi())  .... for every i   (1)
getId<Bi>() != getId<Bj>()       .... when i!=j     (2)

The B1 B2 is just a notation, they are longer names without integer in real life.

How to implements both functions?

Requirements :
1. I don't have to edit all Bi.h (B1 B2 ... class), because there are a lot of them.
2. Assignment integer for each class manually is not allowed, because it is tedious.
3. typeid or dynamic_cast can't be used, because it is slow (I tried.)
4. template is ok
5. non deterministic is ok
6. (bonus) If the generated integer is low-value (Ex. B1=1, B2=2 ...) , it would be nice.

The result (integer) will be used for a hash function.

I have searched, but not find any solution that meet both (1)&(2).
For example, Efficient way to generate id unique to class? is not helpful enough.

Upvotes: 0

Views: 396

Answers (2)

Kenny Ostrom
Kenny Ostrom

Reputation: 5871

My answer is not a fancy template thing, because I thought that was already provided in the other thread you linked, saying it is not good enough. But I do have a way around your dilemma, even if I am bending some of the requirements.

You have a base class, and many many virtual subclasses. I will assume that virtual int get_id() const=0; is a possibility, since it is already a virtual base. That's what most people would immediately do, but you are retrofitting this on a large existing system, and can't manually assign all those id's.

It's too tedous, if only we had a computer ... oh wait.

You can get all the class names by searching your headers for something like grep ": public class A", or if they are too spread out and inconsistently written to get them easily from the headers, then just make get_id pure, and grep the compiler error messages to get all those class names. Dump the output to a file. Now, write a quick and dirty python script to read each line from that output, and write

print "int {}::get_id() const {{ return {}; }}".format(classname, linenumber)

I omitted the details of pulling the classname out with re, because you can do that in grep or the script or write a short c++ helper. The point is, you can output this to a new cpp file, and (with the right includes), you now have automatically assigned id's to each class.

It does not assign id's to new classes, but at least it won't be too tedious from now on, especially if you keep get_id pure.

Upvotes: 1

Cornstalks
Cornstalks

Reputation: 38238

It's not entirely clear how you want this to work, but the following fulfills all your requirements:

#include <tuple>

struct A {};

struct B0 : A {};
struct B1 : A {};
struct B2 : A {};
struct B3 : A {};

void get_id(...) {}

// Just register your types here:
using types = std::tuple<B0, B1, B2, B3>;

template <int N>
void getId() {
    using T =  typename std::tuple_element<N, types>::type;
    get_id(new T()); // This is leaking memory since there is no delete anywhere
}

int main() {
  getId<0>(); // equivalent to get_id(new B0());
  getId<1>(); // equivalent to get_id(new B1());
  getId<2>(); // equivalent to get_id(new B2());
  getId<3>(); // equivalent to get_id(new B3());
}

If you want to know what the index is for a given type there are ways of doing that.

Upvotes: 0

Related Questions