Reputation: 10234
I have a template function to give me a unique id based on the typename
passed to it, like this:
template<typename T>
inline std::size_t get_component_type_id() noexcept
{
static_assert(std::is_base_of<Component, T>::value, "T must be of type Component.");
static size_t uniqueComponentId{__INTERNAL__::getUniqueComponentId()};
return uniqueComponentId;
}
When I call get_component_type_id
with BaseClass
10 times, I get the same id. That works perfectly.
However, I want to get the same id as well if I pass a child class to that function. When I call it with ChildClass
, I get a different id. Why is that?
Upvotes: 4
Views: 888
Reputation: 206577
get_component_type_id<BaseClass>
and get_component_type_id<ChildClass>
are two different functions. Hence, you get two of static size_t uniqueComponentId
, each with their own value.
Update, in response to comment by OP
Yes, it is possible. You could use:
template <typename T>
inline std::size_t get_component_type_id(T*, std::false_type) noexcept
{
static size_t uniqueComponentId{__INTERNAL__::getUniqueComponentId()};
return uniqueComponentId;
}
inline std::size_t get_component_type_id(BaseClass*, std::true_type) noexcept
{
static size_t uniqueComponentId{__INTERNAL__::getUniqueComponentId()};
return uniqueComponentId;
}
template<typename T>
inline std::size_t get_component_type_id() noexcept
{
static_assert(std::is_base_of<Component, T>::value, "T must be of type Component.");
return get_component_type_id((T*)nullptr, typename std::is_convertible<T, BaseClass>::type{});
}
However, it is fragile. If you want the same behavior for another class derived from Component
, you will need to make substantial changes.
You will be better off using a virtual
member function.
struct Component
{
virtual size_t get_type_id() const = 0;
};
struct BaseClass : Component
{
size_t get_type_id() const
{
static size_t uniqueComponentId{__INTERNAL__::getUniqueComponentId()};
return uniqueComponentId;
}
};
struct ChildClass : BaseClass {};
Now you can implement size_t get_type_id() const
at any level in the inheritance hierarchy as you see fit.
Upvotes: 2
Reputation: 2837
You can try adding a function that calls get_component_type_id()
with Component
as the template argument when the actual T
is a child of Component
.
template<class T>
auto fn() noexcept
{
using type = std::conditional_t<std::is_base_of<Component, T>::value, Component, T>;
return get_component_type_id<type>();
}
Upvotes: 4
Reputation: 122460
This is because an instantiation of a template, once instantiated, has nothing to do with a second instantiation of the same template. The two are seperate entities and get their own static variable.
PS: Here is a video where this occurs in an example: CppCon 2015: Arthur O'Dwyer “Lambdas from First Principles: A Whirlwind Tour of C++"”. The example starts aroung 6:00
Upvotes: 5