operator== für struct automatisch definieren?
-
Wie kann ich in C++11 einen operator== für einen
struct S { unsigned d: 4; unsigned c: 4; unsigned b: 1; unsigned a: 1; };
automatisch definieren lassen?
-
lol, lass das mit den Bitsets und berechne die Zugriffe selber.
-
So direkt gar nicht. Du könntest höchstens ein tupel nehmen, das bringt den Vergleichsoperator bereits mit. Ansonsten könntest du die mal boost/operators anschauen, das könnte vielleicht das sein, was du suchst.
Edit: Ups, hatte nicht gesehen, das das ein Bitset ist, da gelten wahrscheinlich andere Regeln.
-
automatisch definieren lassen?
Gar nicht. Obwohl... moeglicherweise koennte man ein Template schreiben, welches die Adressen der Member als Template-Parameter nimmt und ... ja, das koennte funktionieren, ich bin nur gerade in der Schule, daher...
Edit: Ich probiere es mal bei Ideone.
-
Heureka!
#include <iostream> #include <algorithm> using namespace std; template< typename Base, typename... T > struct Comparer { template< T Base::* ... ptr > struct Members { static bool compare( Base const& lhs, Base const& rhs ) { bool arr[]{ ( lhs.*ptr == rhs.*ptr )... }; return all_of( begin(arr), end(arr), [](bool b){return b;} ); } }; }; struct A { int a; char b; }; int main() { A a{4, '7'}, b=a, c{5, '7'}; cout << Comparer<A, int, char>::Members<&A::a, &A::b>::compare(a, b); cout << Comparer<A, int, char>::Members<&A::a, &A::b>::compare(a, c); }
Scheint zu funktionieren
Muss man nur noch so umschreiben, dass man nicht die Typen der Member redundanterweise angibt. Das sollte auch recht einfach gehen.
Edit: Den Typ der Klasse muss man eigentlich auch nicht angeben...
-
Arcoth schrieb:
moeglicherweise koennte man ein Template schreiben, welches die Adressen der Member als Template-Parameter nimmt
Mit Bitfeldern wird das allerdings nichts.
-
Habe es fertig:
#include <iostream> #include <algorithm> using namespace std; template< typename Base, typename... T > struct Comparer { template< T Base::* ... ptr > struct Members { static bool compare( Base const& lhs, Base const& rhs ) { bool arr[]{ ( lhs.*ptr == rhs.*ptr )... }; return all_of( begin(arr), end(arr), [](bool b){return b;} ); } }; }; template< typename T > struct get_type; template< typename Type, typename Class > struct get_type<Type Class::*> { using type = Type; using class_type = Class; }; template<typename...> struct type_list; template<typename ... Args> type_list<Args...> get_types( Args... ); template<typename> struct create_comparer; template< typename First, typename ... Tail > struct create_comparer<type_list<First, Tail...>> : Comparer<typename get_type<First>::class_type, typename get_type<First>::type, typename get_type<Tail>::type...> {}; #define CREATE_COMPARER(...) create_comparer<decltype(get_types(__VA_ARGS__))>::Members<__VA_ARGS__> struct A { int a; char b; }; int main() { A a{4, '7'}, b=a, c{5, '7'}; cout << CREATE_COMPARER(&A::a, &A::b)::compare(a, b); cout << CREATE_COMPARER(&A::a, &A::b)::compare(a, c); }
http://ideone.com/F1QGCJ
Geht vielleicht einfacher, sehe ich mir nochmal an wenn ich wieder zuhause bin.camper schrieb:
Ich fordere dich heraus.
??
-
Arcoth schrieb:
camper schrieb:
Ich fordere dich heraus.
??
Wo hast du das Zitat her?
-
Lässt sich noch vereinfachen und vervollständigen:
#include <iostream> #include <algorithm> template< typename Base, typename... MemTypes > struct Comparer { using class_type = Base; template< MemTypes Base::* ... mem_ptr > struct Members { static bool compare( Base const& lhs, Base const& rhs ) { bool arr[]{ ( lhs.*mem_ptr == rhs.*mem_ptr )... }; return std::find( arr, std::end(arr), false) == std::end(arr); } }; }; template< typename Base, typename ... Tail > Comparer<Base, Tail...> create_comparer( Tail Base::*... ); #define COMPARER(...) decltype(create_comparer(__VA_ARGS__)) #define DEFINE_COMPARE( ... ) \ bool operator==( COMPARER(__VA_ARGS__)::class_type const& lhs, \ COMPARER(__VA_ARGS__)::class_type const& rhs ) \ { \ return COMPARER(__VA_ARGS__)::Members<__VA_ARGS__>::compare(lhs, rhs); \ } struct A { int a; char b; }; DEFINE_COMPARE( &A::a, &A::b ) int main() { A a{4, '7'}, b=a, c{5, '7'}; std::cout << (a == b) << ' ' << (a == c); }
Der Vorteil hierbei ist, dass das ganze recht flexibel gestaltet werden kann - die Member die verglichen werden sollen, sowie die Reihenfolge sind frei festlegbar. Für diesen konkreten Fall (dank Bitsets) aber nutzlos.
Hätte nicht gedacht, dass das in 30 Zeilen passt.
~
Edit²: Noch weiter vereinfacht.
EDit³: Noch weiter ... .~camper schrieb:
Arcoth schrieb:
camper schrieb:
Ich fordere dich heraus.
??
Traust du dich etwa nicht?
Doch, schon, aber was soll das?
-
Arcoth schrieb:
camper schrieb:
Arcoth schrieb:
camper schrieb:
Ich fordere dich heraus.
??
Traust du dich etwa nicht?
Doch, schon, aber was soll das?
Spinnt unser lieber Hacker nun völlig?
-
Wie mir gerade (etwas spät) auffällt, ist dabei ja gar keine bedingte Auswertung möglich... das müsste auch gehen, mir fällt nur spontan kein Weg ein...
-
Doch, geht - durch folgende Neudefinition von
Compare
:template< typename Base, typename MemType, typename... MemTypes > struct Comparer { using class_type = Base; template< MemType Base::* first, MemTypes Base::* ... mem_ptr > struct Members { static bool compare( Base const& lhs, Base const& rhs ) { return lhs.*first == rhs.*first && Comparer<Base, MemTypes...>::template Members<mem_ptr...>::compare(lhs, rhs); } }; }; template< typename Base, typename MemType> struct Comparer<Base, MemType> { using class_type = Base; template< MemType Base::* first > struct Members { static bool compare( Base const& lhs, Base const& rhs ) { return lhs.*first == rhs.*first; } }; };
Edit: Ich sollte wohl wissen, das es
Comparator
heißen sollte