模板函数静态变量

时间:2016-06-27 17:33:29

标签: c++ templates

我有一个模板函数,根据传递给它的typename给我一个唯一的ID,如下所示:

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;
}

当我用get_component_type_id拨打BaseClass 10次时,我会获得相同的ID。这非常有效。

但是,如果我将子类传递给该函数,我也希望得到相同的id。当我用ChildClass调用它时,我会得到一个不同的ID。那是为什么?

3 个答案:

答案 0 :(得分:4)

当实际get_component_type_id()Component的孩子时,您可以尝试添加以TComponent作为模板参数的函数。

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>();
}

答案 1 :(得分:3)

这是因为模板的实例化一旦被实例化,就与同一模板的第二实例化无关。这两个是单独的实体,并获得自己的静态变量。

PS:以下是一个视频:CppCon 2015: Arthur O'Dwyer “Lambdas from First Principles: A Whirlwind Tour of C++"”。该示例从6:00开始

答案 2 :(得分:2)

get_component_type_id<BaseClass>get_component_type_id<ChildClass>是两个不同的功能。因此,您得到两个static size_t uniqueComponentId,每个都有自己的值。

更新,以回应OP的评论

是的,有可能。你可以使用:

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{});
}

然而,它很脆弱。如果您希望从Component派生的另一个类具有相同的行为,则需要进行实质性更改。

最好使用virtual成员函数。

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 {};

现在,您可以根据需要在继承层次结构中的任何级别实现size_t get_type_id() const