C++17: Klassen-Member Typen automatisch deduktbar?

Gast #6602180
Lesenswert?

Ich versuche mal wieder einen Haufen Boilerplate Code für eine 
Klassen-interne (De)serialisierung zu vermeiden - der Code steht schon 
lange und läuft aber man muss fuer das (De)serialisieren und die 
vorhergehende Größen-Brechnung der Serialisierungs-Daten mind. 3 mal die 
entsprechende Member angeben - wie gesagt läuft alles, ist mir aber viel 
zu umständlich

jetzt hatte ich mir ueberlegt den bestehenden Serialisierer durch einen 
kleines Helper-Template zu erweitern bei dem man einmalig die Member 
angibt die serialisiert werden sollen und diese Angabe dann an den 
calc_size, encode, decode Stellen verwendet wird

Klappt soweit aber ich würde gerne wissen warum der Serializer innerhalb 
der Test-Klasse nicht in der Lage ist die Member-Typen automatisch zu 
dedukten (Zeile 22), so wie er es in der main kann (Zeile 31)

kann mir das jemand erklären?

gcc-godbolt: https://gcc.godbolt.org/z/PbYb9s
1
#include <tuple>
2

3
template <typename... Member>
4
class Serializer
5
{
6
public:
7
    Serializer( Member&... ref_ ) : m_refs( ref_... )
8
    {
9
    }
10

11
    using refs = std::tuple<Member&...>;
12
    refs m_refs;
13
};
14

15
class Test
16
{
17
public:
18
    int m_x{};
19
    float m_y{};
20

21
    // hier brauche ich noch die typen (oder eben decltype)
22
    Serializer<decltype( m_x ), decltype( m_y )> m_serialize{ m_x, m_y };
23
};
24

25
int main()
26
{
27
    Test t;
28
    std::get<0>( t.m_serialize.m_refs ) = 23; // schreibt m_x
29

30
    // ausserhalb der Klasse geht das automatische dedukting
31
    Serializer s( t.m_x, t.m_y);
32
}
#6602557
Lesenswert?

Statt die Typen als Templateparameter zu übergeben, könnte man auch 
Pointer auf die Membervariablen selbst in einem template übergeben. 
Damit spart man sich schon mal die doppelte Nennung der Member, auch 
wenn dann jeweils der Klassenname benötigt wird: 
https://gcc.godbolt.org/z/Y7azbn

Funktioniert dann natürlich nicht mehr direkt außerhalb der Klasse. Und 
schön ist das auch nicht besonders. Ich hoffe ja noch darauf, dass wir 
irgendwann mal Reflection bekommen...
Gast #6604594
Lesenswert?

Ich würde den Serializer gar nicht als member-variable rumschleppen - 
mit den Pointern kann man doch sonst nichts anfangen.
Mein Ansatz wäre eine Template-Funktion, die ein anderes Template mit 
den Parametern called.
1
struct Test {
2
   int m_x;
3
   float m_y;
4

5
   template<class Callable>
6
   void withMembers(Callable&& callable) {
7
     callable(m_x, m_y);
8
   }
9
};
10

11
int main() {
12
  Test t{1, 2.0f};
13
  t.withMembers([](const auto&... args){
14
     ((std::count<<(args)<<std::endl), ...);
15
  });
16
}
oder so ähnlich.

Was mich aber stutzig macht: Warum wird hier 
https://gcc.godbolt.org/z/Pfb15d zuerst der float behandelt?
Gast #6604930
Lesenswert?

Ich krieche zu Kreuze: Der Compiler macht eine automatische 
Typ-Konvertierung, um einen gültigen Overload mit den rvalues zu haben. 
Weil er die const& aber nicht auf die rvalue&& konvertieren darf, 
konvertiert er halt const int& auf float&& und umgekehrt.
Mit noch einem print(short&&) zB wird das Ganze ambiguous.

Garbage In - Garbage Out

Vermutlich ist VC++ fehlerhaft.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren