Nein, memcmpist dazu nicht geeignet. Und die Reflexion in C ++ reicht zu diesem Zeitpunkt nicht aus, um dies zu tun (es wird experimentelle Compiler geben, die die Reflexion unterstützen, die stark genug ist, um dies bereits zu tun, und c ++ 23 verfügt möglicherweise über die Funktionen, die Sie benötigen).
Ohne eingebaute Reflexion können Sie Ihr Problem am einfachsten durch manuelle Reflexion lösen.
Nimm das:
struct some_struct {
int x;
double d1, d2;
char c;
};
Wir wollen den minimalen Arbeitsaufwand erledigen, damit wir zwei davon vergleichen können.
Wenn wir haben:
auto as_tie(some_struct const& s){
return std::tie( s.x, s.d1, s.d2, s.c );
}
oder
auto as_tie(some_struct const& s)
-> decltype(std::tie( s.x, s.d1, s.d2, s.c ))
{
return std::tie( s.x, s.d1, s.d2, s.c );
}
für c ++ 11 dann:
template<class S>
bool are_equal( S const& lhs, S const& rhs ) {
return as_tie(lhs) == as_tie(rhs);
}
macht einen ziemlich anständigen Job.
Wir können diesen Prozess mit ein wenig Arbeit so erweitern, dass er rekursiv ist. Anstatt Bindungen zu vergleichen, vergleichen Sie jedes Element, das in eine Vorlage eingeschlossen ist, und diese Vorlage operator==wendet diese Regel rekursiv an (das Element as_tiezum Vergleich einschließen), es sei denn, das Element verfügt bereits über eine Funktion ==und verarbeitet Arrays.
Dies erfordert ein bisschen Bibliothek (100 Codezeilen?) Zusammen mit dem Schreiben von manuellen "Reflexions" -Daten pro Mitglied. Wenn die Anzahl Ihrer Strukturen begrenzt ist, ist es möglicherweise einfacher, Code pro Struktur manuell zu schreiben.
Es gibt wahrscheinlich Möglichkeiten zu bekommen
REFLECT( some_struct, x, d1, d2, c )
die as_tieStruktur mit schrecklichen Makros zu generieren . Ist as_tieaber einfach genug. In c ++ 11 ist die Wiederholung ärgerlich; das ist nützlich:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
in dieser Situation und vielen anderen. Mit RETURNSSchreiben as_tieist:
auto as_tie(some_struct const& s)
RETURNS( std::tie( s.x, s.d1, s.d2, s.c ) )
Entfernen der Wiederholung.
Hier ist ein Versuch, es rekursiv zu machen:
template<class T,
typename std::enable_if< !std::is_class<T>{}, bool>::type = true
>
auto refl_tie( T const& t )
RETURNS(std::tie(t))
template<class...Ts,
typename std::enable_if< (sizeof...(Ts) > 1), bool>::type = true
>
auto refl_tie( Ts const&... ts )
RETURNS(std::make_tuple(refl_tie(ts)...))
template<class T, std::size_t N>
auto refl_tie( T const(&t)[N] ) {
// lots of work in C++11 to support this case, todo.
// in C++17 I could just make a tie of each of the N elements of the array?
// in C++11 I might write a custom struct that supports an array
// reference/pointer of fixed size and implements =, ==, !=, <, etc.
}
struct foo {
int x;
};
struct bar {
foo f1, f2;
};
auto refl_tie( foo const& s )
RETURNS( refl_tie( s.x ) )
auto refl_tie( bar const& s )
RETURNS( refl_tie( s.f1, s.f2 ) )
c ++ 17 refl_tie (Array) (vollständig rekursiv, unterstützt sogar Arrays von Arrays):
template<class T, std::size_t N, std::size_t...Is>
auto array_refl( T const(&t)[N], std::index_sequence<Is...> )
RETURNS( std::array<decltype( refl_tie(t[0]) ), N>{ refl_tie( t[Is] )... } )
template<class T, std::size_t N>
auto refl_tie( T(&t)[N] )
RETURNS( array_refl( t, std::make_index_sequence<N>{} ) )
Live Beispiel .
Hier benutze ich ein std::arrayvon refl_tie. Dies ist viel schneller als mein vorheriges Tupel von refl_tie zur Kompilierungszeit.
Ebenfalls
template<class T,
typename std::enable_if< !std::is_class<T>{}, bool>::type = true
>
auto refl_tie( T const& t )
RETURNS(std::cref(t))
Wenn Sie std::crefhier anstelle von std::tieverwenden, können Sie Overhead beim Kompilieren sparen, da dies crefeine viel einfachere Klasse ist als tuple.
Schließlich sollten Sie hinzufügen
template<class T, std::size_t N, class...Ts>
auto refl_tie( T(&t)[N], Ts&&... ) = delete;
Dies verhindert, dass Array-Mitglieder in Zeiger zerfallen und auf die Zeigergleichheit zurückgreifen (was Sie von Arrays wahrscheinlich nicht wollen).
Ohne dies wird, wenn Sie ein Array an eine nicht reflektierte Struktur in übergeben, auf eine Zeiger-zu-nicht-reflektierte Struktur zurückgegriffen refl_tie, die funktioniert und Unsinn zurückgibt.
Dies führt zu einem Fehler bei der Kompilierung.
Die Unterstützung der Rekursion durch Bibliothekstypen ist schwierig. Sie könnten std::tiesie:
template<class T, class A>
auto refl_tie( std::vector<T, A> const& v )
RETURNS( std::tie(v) )
aber das unterstützt keine Rekursion.