C
Quaneu schrieb:
Bei meinem Beispiel schaffe ich es auch ohne polymorphe Basisklasse, da DebugInformationEntryAttribute ein Feld besitzt, das den Typen beinhalten. Somit kann ich in einem switch case static_cast benutzen.
Nichts hindert dich daran, eine eigene cast-Funktion zu schreiben, etwa
#include <type_traits>
#include <typeinfo>
#include <utility>
/////////////
template <typename T> struct tag_val { int val; };
template <typename T, int I> struct derived_tag {};
template <typename... T> struct tag_list;
template <typename... T, int... I> struct tag_list<derived_tag<T, I>...> : tag_val<T>... {
constexpr tag_list() : tag_val<T>{I}... {}
template <typename U>
constexpr int get() const {
return tag_val<U>::val;
}
};
struct base { int tag; };
struct derived1 : base {};
struct derived2 : base {};
struct derived3 : base {};
// Liste mit allen abgeleiteten Klassen mit zugehörigem tag-Wert
constexpr tag_list<
derived_tag<derived1, 1>,
derived_tag<derived2, 2>,
derived_tag<derived3, 3>> derived_tags;
template <typename T, typename std::enable_if<std::is_pointer<T>{}>::type* = nullptr>
T my_polymorphic_cast(base* p) {
return p && derived_tags.get<typename std::remove_pointer<T>::type>() == p->tag ? static_cast<T>( p ) : nullptr;
}
template <typename T, typename std::enable_if<std::is_reference<T>{}>::type* = nullptr>
T my_polymorphic_cast(base& p) {
auto q = my_polymorphic_cast<typename std::remove_reference<T>::type*>( &p );
return q ? q : throw std::bad_cast();
}
#include <iostream>
int main() {
derived1 a; a.tag = 1;
base* p = &a;
std::cout << (my_polymorphic_cast<derived1*>(p)!=nullptr) << '\n'
<< (my_polymorphic_cast<derived2*>(p)==nullptr) << '\n';
}