Bestimmung des (Result)-Typs eines Pointer-To-Member via Templates
-
-
mach folgendes:
a)Definiere ein Traits-Template für die Strukturen, wo du den Subtype als typedef drin hast.
b1) Wenn du die Strukturen selber definierst/generierst, packe noch ein typedef für die subtypen rein, im Traits geht das typedef dann auf den typedef im struct.
b2) Für fremddefinierte Strukturen spezialisierst du den traittemplate <class Type> struct MemarrayTraits { typedef Type::subtype subtype; //default: das struct definiert selber den subtype }; template< typename Type > struct ArrayWrapper { typedef MemarrayTraits<Type>::subtype Subtype; //die traits bestimmen den subtype ArrayWrapper( Type*& s ) : m_struct( s ) {} Subtype& value( size_t index ) { return m_struct->item[ index ]; } private: Type*& m_struct; }; // Strukturen struct MyOwnArrayOfX //selbstgeschrieben { size_t size; X* array; typedef X subtype; }; struct TheirArrayOfY //fremdgeschrieben... { size_t size; Y* array; }; //... daher Spezialisierung des traits, weil das struct den subtype nicht definiert templyte<> struct MemarrayTraits<TheirArrayOfY> { typedef Y subtype; };
-
-
pumuckl schrieb:
...
Das wäre die krampfige Methode, von der ich schrieb. Das wird aber ziemlich ätzend, wenn es sehr viele generierte Strukturtypen gibt.
-
Tachyon schrieb:
pumuckl schrieb:
...
Das wäre die krampfige Methode, von der ich schrieb. Das wird aber ziemlich ätzend, wenn es sehr viele generierte Strukturtypen gibt.
Wenn es einen weg gibt, die Strukturtypen zu generieren, dann wirds auch einen Weg geben, die Trait-Spezialisierungen zu generieren

Oder eben den generator umschreiben dass er das typedef noch mit dazubaut.
-
Tachyon schrieb:
Badestrand schrieb:
Und das hilft bei Template-Argumenten genau wie?
Gnarg, scheint echt nicht zu klappen..
-
pumuckl schrieb:
Tachyon schrieb:
pumuckl schrieb:
...
Das wäre die krampfige Methode, von der ich schrieb. Das wird aber ziemlich ätzend, wenn es sehr viele generierte Strukturtypen gibt.
Wenn es einen weg gibt, die Strukturtypen zu generieren, dann wirds auch einen Weg geben, die Trait-Spezialisierungen zu generieren

Oder eben den generator umschreiben dass er das typedef noch mit dazubaut.Also wir haben hier einen Generator, der aus einem IDL-Subset Code für unterschiedliche Sprachen generiert (u.a. C) generiert. Der weiss nichtmal, dass es Templates gibt. Erweiterungen sind da auch nicht denkbar.
Wenn man sowas privat gebastelt hat, klar. Dann kann man das erweitern wie man lustig ist.
Aber in Firmen, wo die Tools gesetzt sind? Wohl eher nicht.
-
Falls ein Makro anstatt einer Funktion in Ordnung ist:
#include <boost/typeof/typeof.hpp> template<class T> struct ExtractMemberType; template<class T, class E> struct ExtractMemberType<E* T::*> { typedef E type; }; struct X; struct ArrayOfX { X* array; }; template< typename Type, typename Subtype > struct ArrayWrapper { ArrayWrapper( Type*& ) { } }; #define ArrayWrapperType(s) ArrayWrapper< BOOST_TYPEOF(*s), ExtractMemberType<BOOST_TYPEOF( &BOOST_TYPEOF(*s)::array )>::type > #define ArrayOf(s) ArrayWrapper< BOOST_TYPEOF(*s), ExtractMemberType<BOOST_TYPEOF( &BOOST_TYPEOF(*s)::array )>::type > (s) // edit: bzw #define ArrayOf(s) ArrayWrapperType(s)(s) template<typename Type> void foo( Type* s ) { ArrayWrapperType(s) asd = ArrayOf( s ); std::cout << typeid(ArrayWrapperType(s)).name() << "\n"; // -> struct ArrayWrapper<struct ArrayOfX,struct X> } int main() { ArrayOfX* s = NULL; foo( s ); }
-
Naja, Sinn der Sache ist ja, möglichst nicht die aussenstehenden Beteiligten (sprich den Generator) zu modifizieren. Der ist nämlich tatsächlich nicht von uns.
Mit BOOST_TYPEOF würde es sogar funktionieren:
template< typename Type > struct result_type_helper { static Type* t; typedef BOOST_TYPEOF( t->item ) type; }; template< typename Type > struct ArrayWrapper { typedef typename result_type_helper< Type >::type Subtype; /* ... */ };Jetzt ist das Problem, dass einer der Compiler hier keine Typeof-Erweiterung kennt, und damit alle Typen wenn ich das richtig verstanden habe "registriert" werden müssen. Das kommt mehr oder weniger der Lösung von pumuckl gleich.
Den Makro-Vorschlag hab ich jetzt noch nicht angeschaut, Beitrag wurde vorher begonnen

-
LordJaxom schrieb:
Naja, Sinn der Sache ist ja, möglichst nicht die aussenstehenden Beteiligten (sprich den Generator) zu modifizieren. Der ist nämlich tatsächlich nicht von uns.
Etwas was mir noch eingefallen ist: Wenn die Structs generiert werden, sidn sie alle nach Schema F gestrickt. Die entsprechende Datei(en) sind auch leicht zu finden. Man könnte dann einen zusätzlichen Generator schreiben, der die "Registrierung" (d.h. Spezialisierung des Traits/Helpertemplates) vornimmt indem er die generierten Dateien parst und die Spezialisierungen schreibt - das parsen ist schnell erledigt, der Generator wäre ein recht kurzes Script, das man problemlos in jeden Buildprozess einbauen kann.
-
#include <boost/type_traits.hpp> struct ArrayOfX { std::size_t n; int* array; }; template<typename X> struct GetMemberType; template<typename C, typename M> struct GetMemberType<M C::*> { typedef M Type; }; template<typename T, typename SubT> struct ArrayWrapper { ArrayWrapper(T*& s) : m_struct(s) { } SubT& value(size_t index) { return m_struct->array[index]; } private: T*& m_struct; }; template<typename T, typename X> ArrayWrapper < T, typename boost::remove_pointer<typename GetMemberType<X>::Type>::type > ArrayOf(T*& s, X) { return ArrayWrapper < T, boost::remove_pointer<typename GetMemberType<X>::Type>::type > (s); } int main() { ArrayOfX obj; ArrayOfX* p = &obj; ArrayOf(p, &ArrayOfX::array); return 0; }Ohne
&ArrayOfX::arrayhabe ich es bisher noch nicht hinbekommen. Man könnte diesen Zeiger allerdings benutzen, falls es abweichende Namen gibt (*). Grundsätzlich könnte die aktuelle Lösung mehr als du verlangst. Sie um diese zusätzlichen Möglichkeiten zu verringern, dass ist mir halt noch nicht gelungen
GetMemberTypeundboost::remove_pointerkönnte man irgendwie noch zusätzlich verknüpfen, falls du möchtest. Ich war jetzt zu faul, dies noch hinzuschreiben.Wieso hälst du eigentlich eine Referenz auf einen Zeiger im
ArrayWrapper? Ist nicht so günstig um einenoperator =vom Kompiler generieren zu lassen
Edit:
* Hier noch der angepasste Code, falls man abweichende Namen hat. Verändert wurdenArrayWrapperundArrayOf:template<typename T, typename SubT> struct ArrayWrapper { typedef typename boost::remove_pointer<SubT>::type value_type; ArrayWrapper(T* s, SubT T::*ptrToMember) : m_struct(s) , m_ptrToMember(ptrToMember) { } value_type& value(size_t index) { return (m_struct->*m_ptrToMember)[index]; } private: T* m_struct; SubT T::* m_ptrToMember; }; template<typename T, typename X> ArrayWrapper < T, typename GetMemberType<X>::Type > ArrayOf(T* s, X ptrToMember) { return ArrayWrapper < T, typename GetMemberType<X>::Type > (s, ptrToMember); }Grüssli
-
Dravere schrieb:
Wieso hälst du eigentlich eine Referenz auf einen Zeiger im
ArrayWrapper? Ist nicht so günstig um einenoperator =vom Kompiler generieren zu lassen
Das ist im Zuge der Verkürzung reingekommen - im Real World Code ist es ein Doppelzeiger

Die Idee mit dem Memberzeiger hatte ich auch schon, da bräuchte man sogar kein Helfertemplate mehr - inkl. dem Versuch, &T::array als Defaultparameter übergeben zu lassen, was der Compiler aber nicht wirklich mochte. Ist aber auch irgendwie klar, wie soll der Compiler auch den zweiten Templateparameter herleiten, bevor das dazugehörige Argument bekannt ist.
/* Verkürzte Version ohne Helper */ struct X { int wert; }; struct ArrayOfX { size_t size; X* array; }; template< typename Struct, typename Type > struct ArrayWrapper { }; template< typename Struct, typename Type > ArrayWrapper< Struct, Type > ArrayOf( Struct*& capsule, Type* ( Struct::*array ) /* = &Struct::array */ ) // das Default-Argument wird, wenn vorhanden, nichtmals angemeckert. Nur ist es kein wirklicher Default, weil der Aufruf mit einem Parameter nicht funktioniert. { return ArrayWrapper< Struct, Type >(); } int main() { ArrayOfX* capsule = 0; ArrayOf( capsule, &ArrayOfX::array ); }Da wäre mir dann aber die Syntax
ArrayOf< X >( capsule );für den Standardfall undArrayOf( capsule, &ArrayOfX::abweichenderName );für den Fall abweichender Namen lieber:// Parameter vertauscht, wegen ArrayOf< Type > template< typename Type, typename Struct > ArrayWrapper< Struct, Type > ArrayOf( Struct*& capsule, Type* ( Struct::*array ) = &Struct::array ) { return ArrayWrapper< Struct, Type >(); }Ich lasse mir aber tatsächlich auch nochmal die Möglichkeit eines Generators für eine automatische Traits-Erstellung durch den Kopf gehen.