2
\$\begingroup\$

I have written the following class to allow me to uniquely identify classes in C++, and I was wondering if there are any better ways of going about it.

#ifndef _TYPE_IDENTIFIER_H_
#define _TYPE_IDENTIFIER_H_

typedef std::size_t Identifier;

class TypeIdentifier {
public:
    template<class T>
    static Identifier get_identifier() {
        static const Identifier current_identifier = ++next_identifier;

        return current_identifier;
    }

private:
    static Identifier next_identifier;
};

Identifier TypeIdentifier::next_identifier = 0;

#endif

And an example of using it:

class MyFirstClass {};
class MySecondClass {};

printf("%zu", TypeIdentifier::get_identifier<MyFirstClass>()); // 1
printf("%zu", TypeIdentifier::get_identifier<MySecondClass>()); // 2

printf("%zu", TypeIdentifier::get_identifier<MySecondClass>()); // 2
printf("%zu", TypeIdentifier::get_identifier<MyFirstClass>()); // 1

I'm using it in an ECS, where there can only be one instance of a certain component in an Entity. I store a vector of structs containing a void pointer to the component and an Identifier type of the component. Using TypeIdentifier::get_identifier<ComponentType>(), I can check the type of a passed component and check if it's already present in the Entity.

\$\endgroup\$
3
  • \$\begingroup\$ Not sure how this helps solve the problem you describe (as template types are compile time defined not run time). Can you show some code on how it is used. \$\endgroup\$ – Martin York Aug 17 '15 at 21:42
  • \$\begingroup\$ Each class is given a different identifier by the code, as the private static variable is shared, but the get_identifier method has a different static const value for each template type. Every type has it's own identifier, and it remains constant for a specific type. E.g. the type ID of MyFirstClass is 1 and the type ID of MySecondClass is 2 (or the other way round, depending on the order of invocation). \$\endgroup\$ – Jack Wilsdon Aug 17 '15 at 23:17
  • \$\begingroup\$ I can read the code and see what it is doing. But I don;t see how that solves your problem. C++ is a statically typed language. All the types are determined at compile time. You can not do runtime ID checking of the clasees. How are you using this is more the question. Maybe you have worked out how to use this at runtime in way I am not spotting but as it stands seems to provide little benefit. \$\endgroup\$ – Martin York Aug 18 '15 at 0:52
1
\$\begingroup\$

Well you can use typeid.

printf("%zu", typeid(MyFirstClass).hash_code());

Not sure how

TypeIdentifier::get_identifier<MyFirstClass>()
     //                       ^^^^^^^^^^^^    Compile time type.
     //  This will not help with runtime
     //  type checking.

is going to help you.

Assuming the above is in a single header file (because of include guards).

Then this:

Identifier TypeIdentifier::next_identifier = 0;

Is in the wrong place. It will be defined for every compilation unit that includes the header. Personally I would use a function rather than a static value.

class TypeIdentifier {
public:
    template<class T>
    static Identifier get_identifier() {
        static const Identifier current_identifier = getNext();
        return current_identifier;
    }

private:
    static Identifier getNext() {
        static Identifier next_identifier = 0;
        return next_identifier++;  //
    }
};
\$\endgroup\$
1
  • \$\begingroup\$ I figure he has good reasons for prefering a compile-time solution, but it will be necessary to use a static local in a static member function to store his next_identifier, just like you have here. \$\endgroup\$ – Christopher Oicles Feb 19 '16 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.