1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_RuntimeTypeInfo.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision:$
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_UT_RUNTIMETYPEINFO_H_
17 #define NW_UT_RUNTIMETYPEINFO_H_
18 
19 #include <stddef.h>
20 #include <nw/types.h>
21 
22 namespace nw {
23 namespace ut   {
24 
25 //--------------------------------------------------------------------
26 // ダイナミックキャストを可能にする為に埋め込むべき実行時型情報を
27 // メンバに含めるマクロです。
28 // クラスの宣言中に記述します。
29 //--------------------------------------------------------------------
30 #define NW_UT_RUNTIME_TYPEINFO \
31     virtual const nw::ut::internal::RuntimeTypeInfo*    GetRuntimeTypeInfo() const { return &s_TypeInfo; } \
32     static  const nw::ut::internal::RuntimeTypeInfo     s_TypeInfo
33 
34 
35 //--------------------------------------------------------------------
36 // クラスの実行時型情報の実体を定義するマクロです。
37 //
38 // ルートクラスの場合には、
39 //    NW_UT_RUNTIME_TYPEINFO_ROOT_DEFINITION(クラス名);
40 // 派生クラスの場合には、
41 // NW_UT_RUNTIME_TYPEINFO_DEFINITION(クラス名、ベースクラス名);
42 // の形式で記述します。
43 //--------------------------------------------------------------------
44 #define NW_UT_RUNTIME_TYPEINFO_DEFINITION(derived,base) \
45     const nw::ut::internal::RuntimeTypeInfo derived::s_TypeInfo( &base::s_TypeInfo )
46 
47 #define NW_UT_RUNTIME_TYPEINFO_ROOT_DEFINITION(root) \
48     const nw::ut::internal::RuntimeTypeInfo root::s_TypeInfo( NULL )
49 
50 
51 namespace internal {
52 
53 //--------------------------------------------------------------------
54 //
55 // 実行時型情報構造体
56 //
57 //--------------------------------------------------------------------
58 struct RuntimeTypeInfo
59 {
60     const RuntimeTypeInfo*  mParentTypeInfo;
61 
RuntimeTypeInfoRuntimeTypeInfo62     /* ctor */ explicit  RuntimeTypeInfo( const RuntimeTypeInfo* parent ) : mParentTypeInfo( parent ) {}
63 
IsDerivedFromRuntimeTypeInfo64     bool                 IsDerivedFrom( const RuntimeTypeInfo* s_TypeInfo ) const
65     {
66         const RuntimeTypeInfo *self = this;
67 
68         while ( self )
69         {
70             if ( self == s_TypeInfo )
71             {
72                 return true;
73             }
74             self = self->mParentTypeInfo;
75         }
76         return false;
77     }
78 };
79 
80 //
81 // ポインタからstaticメンバを取得
82 // Derived* pDerived = DynamicCast<Derived*>( pBase );
83 // と書けるようにするためのテンプレート関数
84 //
85 template<class T>
86 NW_INLINE const RuntimeTypeInfo*
GetTypeInfoFromPtr_(T *)87 GetTypeInfoFromPtr_(T* /* _dummy */)
88 {
89     return &T::s_TypeInfo;
90 }
91 
92 }   /* namespace internal */
93 
94 //----------------------------------------
95 //! @name 基礎
96 //@{
97 
98 //! @brief ダウンキャスト用テンプレート関数です。
99 template<class UPtr, class T>
100 NW_INLINE UPtr
DynamicCast(T * obj)101 DynamicCast(T* obj)
102 {
103     const internal::RuntimeTypeInfo* s_TypeInfoU = internal::GetTypeInfoFromPtr_( UPtr(0) );
104     if ( obj && obj->GetRuntimeTypeInfo()->IsDerivedFrom( s_TypeInfoU ) )
105     {
106         return static_cast<UPtr>(obj);
107     }
108     return NULL;
109 }
110 
111 
112 //--------------------------------------------------------------------------
113 //! @brief        型の比較をおこないます。
114 //!
115 //! @param[in]    instance 型を比較するインスタンスです。
116 //!
117 //! @return       テンプレート引数に指定した型と同一のインスタンスであれば真を返します。
118 //---------------------------------------------------------------------------
119 template <typename T, typename U>
120 NW_INLINE bool
IsTypeOf(const U * instance)121 IsTypeOf(const U* instance)
122 {
123     if (instance == NULL) { return false; }
124     return instance->GetRuntimeTypeInfo() == &T::s_TypeInfo;
125 }
126 
127 //@}
128 
129 } // namespace ut
130 } // nemespace nw
131 
132 // NW_UT_RUNTIMETYPEINFO_H_
133 #endif
134