1
\$\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\$ Aug 17, 2015 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\$ Aug 17, 2015 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\$ Aug 18, 2015 at 0:52

1 Answer 1

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\$ Feb 19, 2016 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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