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.


  • Mod

    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.


  • Mod

    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...


  • Mod

    Arcoth schrieb:

    moeglicherweise koennte man ein Template schreiben, welches die Adressen der Member als Template-Parameter nimmt

    Mit Bitfeldern wird das allerdings nichts.


  • Mod

    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.

    ??


  • Mod

    Arcoth schrieb:

    camper schrieb:

    Ich fordere dich heraus.

    ??

    Wo hast du das Zitat her?


  • Mod

    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?


  • Mod

    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...


  • Mod

    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 😃


Log in to reply