Nein, memcmp
ist 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_tie
zum 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_tie
Struktur mit schrecklichen Makros zu generieren . Ist as_tie
aber 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 RETURNS
Schreiben as_tie
ist:
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::array
von 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::cref
hier anstelle von std::tie
verwenden, können Sie Overhead beim Kompilieren sparen, da dies cref
eine 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::tie
sie:
template<class T, class A>
auto refl_tie( std::vector<T, A> const& v )
RETURNS( std::tie(v) )
aber das unterstützt keine Rekursion.