[英]Automate LLVM style RTTI code
對於特定的類層次結構,我需要知道基類引用是否是特定派生類的實例。 由於不同的原因,我不能在這里使用標准的C ++ RTTI,我需要實現自定義的instanceof
機制。
LLVM-stle RTTI可滿足我的需求,但我想知道它是否存在(以某種方式使用模板)自動化classof
方法的實現?
是否有其他/更簡單的實現這種機制,可以知道基類是否是派生類的實例?
我的約束:
我想知道它是否存在一種方式(以某種方式使用模板)來自動化classof方法的實現?
是的,有一些方法可以自動化classof方法,我真的不明白為什么LLVM頁面會演示一組手動的類方法,因為如果你自動化這個非常簡單的過程它會更具可伸縮性。
這是一個非常基本的解決方案:
class TypedObject {
public:
virtual ~TypedObject() { };
virtual int getClassId() const { return 0; };
static int getStaticClassId() { return 0; };
virtual bool isOfType(int aID) const { return (aID == 0); };
template <typename T>
bool isOfClass() const { return isOfType( T::getStaticClassId() ); };
};
運行時強制轉換(即dynamic_cast
)函數如下所示:
template <typename T>
T* runtime_ptr_cast(TypedObject* p) {
if( (p) && (p->isOfClass<T>()) )
return static_cast<T*>( p );
return NULL;
};
template <typename T>
typename std::enable_if<
std::is_const< T >::value,
T* >::type runtime_ptr_cast(const TypedObject* p) {
if( (p) && (p->isOfClass<T>()) )
return static_cast<T*>( p );
return NULL;
};
那么,你需要的只是MACRO來自動創建虛擬和靜態函數:
#define MY_RTTI_SYSTEM_CREATE_TYPE_1_BASE( NEWCLASSID, BASECLASSNAME ) \
public: \
virtual int getClassId() const { return NEWCLASSID; }; \
static int getStaticClassId() { return NEWCLASSID; }; \
\
virtual bool isOfType(int aID) const { \
return ((aID == NEWCLASSID) || BASECLASSNAME::isOfType(aID)); \
};
然后,您可以創建一個這樣的新類:
class Foo : public TypedObject {
// ... some code, as usual ...
// call the macro with a given ID number and the name of the base-class:
MY_RTTI_SYSTEM_CREATE_TYPE_1_BASE(1, TypedObject)
};
這導致:
int main() {
Foo f;
TypedObject* b = &f;
// check the type:
if( b->isOfClass<Foo>() )
std::cout << "b is indeed for class Foo!" << std::endl;
// make a dynamic cast:
Foo* pf = runtime_ptr_cast<Foo>( b );
if( pf )
std::cout << "cast to 'Foo*' was successful!" << std::endl;
const TypedObject* cb = b;
const Foo* cpf = runtime_ptr_cast<const Foo>( cb );
if( cpf )
std::cout << "cast to 'const Foo*' was successful!" << std::endl;
Foo* pf2 = runtime_ptr_cast<Foo>( cb ); // ERROR: no such function (invalid cast).
};
當然,您也可以通過創建更多MACRO來注冊類型來將其擴展為多重繼承。 這個方案也有無數的變化(個人而言,在我的實現中 ,我將類型注冊到全局存儲庫並且也可以訪問工廠函數)。
我認為沒有任何實際的方法可以避免在您創建的每個類中使用MACRO調用。 我已經考慮了一段時間(前段時間,因為我自己制作)並且我得出結論,最簡單和最干凈的解決方案是在課堂上進行MACRO調用(盡管我對MACROs有很大的蔑視)一般)。 但我不知道,也許其他人有一個更好的(基於模板的)解決方案,這不會導致太多的混亂或不是太介入。 我已經使用這個計划多年了,它非常干凈整潔。
我沒有多重繼承,但我有幾個級別的繼承。
上述方案適用於任何繼承級別(即,它是可擴展的解決方案)。 如果有一天你想這樣做,它也可以很容易地適應多重繼承。
對內存占用的影響必須盡可能小
我知道LLVM更喜歡沒有任何虛函數的解決方案,而是在基類中使用整數id數據成員。 使用這種方案實現與上述相同類型的功能變得有點困難(但可能)。 使用虛函數要容易得多,虛函數只占用一個指針(vtable指針)的空間,這通常不比整數id數據成員大。 如果類已經是多態的,那么成本就沒有了。 當然,上面的內容比內置的C ++ RTTI輕得多。 所以,除非你真的想用一個整數id(或枚舉)解決方案來擠出那些你可以備用的字節,我建議你選擇一個基於虛函數的解決方案,就像我上面所說的那樣。
無法執行動態分配。
通常不需要動態分配。 只有更復雜(和功能豐富)的RTTI實現才需要一些動態分配。 如果你想要的只是能夠做“classof()”(因此,動態轉換),那么肯定不需要動態內存分配。
您希望某種樹(如數據結構)作為全局變量來存儲您的類層次結構
class Foo : public Foo_Parent {
IS_PART_OF_HIERARCHY
public:
Foo();
...
}
#define IS_PART_OF_HIERARCHY
private:
static Hierarchy<string> *node;
public:
bool isChildOf( string parent ) const;
bool isParentOf( string child ) const;
在.cpp文件中
INSERT_INTO_HIERARCHY( Foo, Foo_Parent )
Foo::Foo() {}
....
#define INSERT_INTO_HIERARCHY( class_name, parent_class_name )
Hierarchy<string> class_name::node = classes_hierarchy.insertAfter( #parent_class_name );
bool class_name::isChildOf const( string ) {
auto *node = class_name::node;
// traverse the parents of node
}
bool class_name::isParentOf const( string ) {
auto *node = class_name::node;
// traverse the children of node
}
我在STL中找不到層次結構類,實現一個層次結構很難,我不知道是否值得付出努力。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.