如果我正確地理解了你,你想要一個類型爲inheritance_checker
,這樣它的每個實例都與一個類型相關聯,但是inheritance_checker
本身不是。類似於type_ifo
,但可以在運行時檢查繼承關係。例如,你想以下工作:
class A {};
class B : public A {};
// Note that a and b have the same type but they are "related" to distinct types.
inheritance_checker a = inheritance_checker::create<A>();
inheritance_checker b = inheritance_checker::create<B>();
assert( a.is_base_of (b));
assert( a.derives_from(a)); // derives from or is equal to
assert(! b.is_base_of (a));
assert( b.derives_from(b)); // derives from or is equal to
如果是這樣的話,我可以建議你的東西,不幸的是,可能很慢!這取決於例外。
基本的想法是,如果你拋出B*
然後catch (A*)
是匹配。因此,我們給inheritance_checker
投擲和捕捉在施工時給出的類型的指針的能力。但inheritance_checker
不是模板,因此必須以類型擦除的方式提供此容量。這可以通過存儲具有固定簽名的函數的指針來實現,該簽名不依賴於在構造時傳遞的類型,但能夠引發/捕獲指定類型的指針。下面給出了inheritance_checker
的可能實現。
#include <cassert>
class inheritance_checker {
typedef void (*thrower_t)();
typedef bool (*catcher_t)(thrower_t);
public:
template <typename T>
static inheritance_checker create() {
return inheritance_checker(concrete_thrower<T>, concrete_catcher<T>);
}
bool is_derived_from(const inheritance_checker& other) const {
return other.catcher_(thrower_);
}
bool is_base_of(const inheritance_checker& other) const {
return catcher_(other.thrower_);
}
private:
template <typename T>
static void concrete_thrower() {
throw static_cast<T*>(nullptr);
}
template <typename T>
static bool concrete_catcher(thrower_t thrower) {
try { thrower(); }
catch (T*) { return true; }
catch (...) { }
return false;
}
inheritance_checker(thrower_t thrower, catcher_t catcher) :
thrower_(thrower), catcher_(catcher) {
}
thrower_t thrower_;
catcher_t catcher_;
};
class A {};
class B : public A {};
class C : public B {};
class D {};
int main() {
auto a = inheritance_checker::create<A>();
auto b = inheritance_checker::create<B>();
auto c = inheritance_checker::create<C>();
auto d = inheritance_checker::create<D>();
assert(a.is_base_of(a));
assert(a.is_base_of(b));
assert(a.is_base_of(c));
assert(!a.is_base_of(d));
assert(a.is_derived_from(a));
assert(!a.is_derived_from(b));
assert(!a.is_derived_from(c));
assert(!a.is_derived_from(d));
assert(!b.is_base_of(a));
assert(b.is_base_of(b));
assert(b.is_base_of(c));
assert(!b.is_base_of(d));
assert(b.is_derived_from(a));
assert(b.is_derived_from(b));
assert(!b.is_derived_from(c));
assert(!b.is_derived_from(d));
assert(!c.is_base_of(a));
assert(!c.is_base_of(b));
assert(c.is_base_of(c));
assert(!c.is_base_of(d));
assert(c.is_derived_from(a));
assert(c.is_derived_from(b));
assert(c.is_derived_from(c));
assert(!c.is_derived_from(d));
assert(!d.is_base_of(a));
assert(!d.is_base_of(b));
assert(!d.is_base_of(c));
assert(d.is_base_of(d));
assert(!d.is_derived_from(a));
assert(!d.is_derived_from(b));
assert(!d.is_derived_from(c));
assert(d.is_derived_from(d));
}
如果你願意,你可以一個type_info*
成員添加到inheritance_checker
,以獲得額外的功能,type_info
提供。
請注意is_base_of
和derives_from
之間的對稱性。其實,你可以刪除其中的一個。
我建議你閱讀this文章。
模板是編譯時評估的,你有一個'type_info'表示對象的運行時類型。這應該如何實現?你已經知道它們的靜態類型,它是'object *'(這也是'decltype(* objects.begin())'將會返回),但這對你沒有任何幫助。所以模板完全沒有問題,因爲解決了完全不同的問題,不能用於RTTI。 – 2013-04-05 11:51:43