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