2016-06-27 3 views
4

このように私は、私に渡されたtypenameに基づいて一意のIDを与えるためにテンプレート機能を持っている:私はBaseClass 10回get_component_type_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; 
} 

、私は同じIDを取得。それは完全に機能します。

しかし、私はその関数に子クラスを渡すと同じIDを取得したいと思います。私がChildClassと呼んだとき、私は別のIDを取得します。何故ですか?

+0

の可能性のある重複した[.hファイルに定義を持つテンプレートクラスの静的メンバ変数にどうしますか](http://stackoverflow.com/questions/7108914/what-should-happen-to-template- class-static-member-variables-with-definition-in) – kfsone

答えて

3

これは、一度インスタンス化されたテンプレートのインスタンス化は、同じテンプレートの2回目のインスタンス化とは関係がないためです。 2つは独立したエンティティで、独自の静的変数を取得します。

PS:これは例のビデオがあります:CppCon 2015: Arthur O'Dwyer “Lambdas from First Principles: A Whirlwind Tour of C++"”です。この例では、起動が開始されます。6:00

2

get_component_type_id<BaseClass>get_component_type_id<ChildClass>は2つの異なる機能です。したがって、static size_t uniqueComponentIdの2つが得られ、それぞれ独自の値があります。

アップデートは、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を実装することができます。

+1

私が望むものを達成することは可能ですか? –

4

実際のTComponentの子である場合、get_component_type_id()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>(); 
}