C++ templates are blueprints and don’t represent specific types until they are instantiated with actual types. Once instantiated, the compiler creates a specific version of that template for the provided type. For template classes, each instantiation has its own unique version of the static members, making them distinct for each type the template is instantiated with.

/////////////////////
// Code Block 1
/////////////////////
#include<iostream>

class ComponentBase{
protected:
    // component_type_count is a static variable shared by derived classes
    static inline size_t component_type_count = 0; 
};

template<typename T>
class Component : public ComponentBase{
public:
    static size_t component_type_id(){
        // ID is the static local variable for a particular type T
        static size_t ID = component_type_count++;  
        return ID;     
    }
};
class A : public Component<A>
{};
class B : public Component<B>
{};
class C : public Component<C>
{};
int main()
{
    std::cout << A::component_type_id() << std::endl;  // 0
    std::cout << B::component_type_id() << std::endl;  // 1
    std::cout << B::component_type_id() << std::endl;  // 1
    std::cout << A::component_type_id() << std::endl;  // 0
    std::cout << A::component_type_id() << std::endl;  // 0
    std::cout << C::component_type_id() << std::endl;  // 2
}

Key Points:

  • component_type_count belongs to the base class ComponentBase but shared by all derived classes.
  • A unique ID belongs to every instantiated class (e.g., A, B, C).

In code block 1, the component_type_id() function has a static local variable ID. When this function is called for the first time for a particular type T, the ID variable is initialized with the current value of component_type_count and then component_type_count is incremented. For all subsequent calls to this function for the same type T, the ID variable retains its value from the first call and just returns that value. Essentially, each type T gets a unique ID the first time this function is called, and the same ID is returned for all subsequent calls.

/////////////////////
// Code Block 2
/////////////////////
template<typename T>
class Component : public ComponentBase{
public:
    static size_t component_type_id(){
        return component_type_count++;
    }
};
// print: 0 1 2 3 4 5

In code block 2, the component_type_id() function increments and returns the value of component_type_count every time it’s called, regardless of the type T. So, unlike the first block, every call to component_type_id() for a given type T will return a new, incremented value.