Zur Laufzeit Liste von unterstützten Schnittstellen eines Objektes erfahren
-
Hrmmmm.... hrmmm! Das könnte ich in meinen derzeitigen Ansatz als Optimierung für die "Implements"-Routine natürlich einpflegen, danke für den Tipp! Im Moment sind die Ids nur stinknormale fortlaufende Zahlen, die eben als Statische Member beim Programmstart verteilt werden, oder halt zur Laufzeit, wenn etwas dynamisches in's Spiel kommt.
Als lustige Beinote: Ich hab' ja eben schon auf die Konstruktor-Problematik hingewiesen, also habe ich die Ableitung aus dem "Reflects" herausgenommen, allerdings hatte ich dann auf einmal das Problem, dass das "vtable"-Zeiger-Analog in den Basisklassen offenbar nicht gesetzt wurde. Aber das lag nur daran, dass ich in der falschen Reihenfolge abgeleitet habe... Also mein Ansatz ist auch problematisch, wenn man nicht darauf achtet...
-
Nur ins Blaue hinein geraten: könnte es sein, dass der ICE nicht auftritt, wenn dem Compiler /vmv oder /vmm mitgegeben wird?
Wenn ja, dann wäre das Nichtfunktionieren by Design; die Tatsache, dass es zum ICE kommt und keine ordentliche Fehlermeldung dann nat. trotzdem ein Bug.
-
Hallo!
Danke, für den Tipp, ich habe gerade mal nacheinander alle drei Optionen explizit für den minimalen Testcase angegeben, sie hatten keinen Einfluss auf den ICE.
-
Zumal laut Doku auch die allgemeinste Repräsentation "/vmv" die Normal-Einstellung sei und ich daran nie etwas gedreht habe, es sei denn das passierte irgendwie implizit.
-
Also weitere Detail zum Fehler: Der tritt nur auf, wenn der Methoden-Zeiger sozusagen "die Klasse verlässt", also wie in dem Beispiel bei einem "unabhängigen" Typ "template_func" mitgegeben wird um dann hintenrum wieder in der Klassenhierarchie zu landen. Deshalb war mein erster Repro-Versuch auch fehlerhaft, da ich eine Basisklasse direkt den Zeiger mitgegeben hatte.
-
Hrmmm, nachdem das alles erstmal funktioniert hat und ich nun bei der Vereinfachung bin (das war zwischendurch ziemlich undurchsichtig^^), bin ich etwas verblüfft, wie mächtig doch die Funktionsüberladungs-Auflösung vor allem im Zusammenspiel mit decltype ist. Mir kommt es im Moment so vor, als wäre sie in VC++ vielleicht etwas zu mächtig?
Folgendes Beispiel:
template< typename... Ts > struct list {}; template< typename Class, typename... Args > struct some_base {}; struct some_struct : public some_base< some_struct, int, float, double > {}; template< typename Class, typename... Args > list<Args...> deduce_args( some_base<Class,Args...>& ); int main() { some_struct val; decltype(deduce_args(val)) thelist; }Und das kompiliert bei mir durch! Nicht nur muss er also val zur Basisklasse casten, ohne dass er eigentlich den exakten Typ des Arguments kennt, danach erst kann er damit anfangen gegen die Template-Argumente zu matchen. Und die Template-Basisklassen sind ja eigentlich gar nicht zusammengehörig. Klar ist das alles möglich, aber an anderen Stellen stellt sich der Compiler doch auch so blöde an, warum geht er hier so weit? Ist das überhaupt legal? Und wenn ja, welche Regeln befolgt er hier?
-
Und weiter geht's im Karton mit dem Ausnutzen der Overload-Resolution:
#include <iostream> #include <type_traits> using namespace std; template< typename Class, typename BaseList, typename InterfaceList > struct Reflects {}; template< typename Class, typename BaseList, typename InterfaceList > std::true_type is_reflecting_impl(Class*, Reflects<Class, BaseList, InterfaceList >* ); template< typename Class > std::false_type is_reflecting_impl(Class*, ...); template< typename T > struct is_reflecting : public decltype(is_reflecting_impl<T>((T*)nullptr, (T*)nullptr)) {}; struct A : public Reflects< A, int, float > {}; struct B {}; struct C : public A, public Reflects< C, float, double > {}; struct D : public A {}; int main() { std::cout << is_reflecting<A>::value << "\n"; std::cout << is_reflecting<B>::value << "\n"; std::cout << is_reflecting<C>::value << "\n"; std::cout << is_reflecting<D>::value << "\n"; return 0; }Das spart eine Pseudo-Basisklasse "ReflectingClass<T>", die ich ohne Ausnutzen der Overload-Resolution gebraucht hätte, um per Template-Spezialisierung herauszufinden, ob eine Klasse reflektiert.
Irgendwie ist das viel mächtiger als direkte Template-Spezialisierung OoAber das einzige, was ich dazu finde sind ein paar Dokumente zur Overload-Resolution von IBM, die geben aber soweit ich das sehe kein Beispiel dazu, wie der Compiler zuerst zu einer Basisklasse castet und dann erst versucht das Template zu matchen...
Kann mir jemand den Paragraphen im Standard nennen, der erklärt wie das funktioniert? Vielleicht finde ich noch irgendwo einen Draft.
-
14.8.2.1 /4
-
Alles klar, vielen Dank, Du bist echt ein Lexikon!
Es ist also explizit eine Regel im Standard integriert worden, damit das funktioniert. Kam die Regel erst im Zuge von decltype hinzu, oder funktionierte das schon immer?
Ich hatte jetzt befürchtet, dass der Grund aus dem das funktioniert inhärent im restlichen Überladungs-Mechanismus (Also Kombination von einzelnen Eigenschaften) steckte, sodass ich davon ausging, dass ich da etwas fundamental nicht verstanden habe...
Wie dem auch sei, schön dass es die Regel gibt
Immerhin habe ich jetzt alles zusammengenommen den ICE umschiffen können und wieder eine Menge gelernt.
-
decimad schrieb:
funktionierte das schon immer?
ja