Forum: PC-Programmierung C++17: Klassen-Member Typen automatisch deduktbar?


von cppbert (Gast)


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
}

von Oliver S. (oliverso)


Lesenswert?

error: use of class template 'Serializer' requires template arguments; 
argument deduction not allowed in non-static class member

Sagt der Compiler, und wird damit wohl recht haben.

Oliver

von cppbert3 (Gast)


Lesenswert?

Oliver S. schrieb:
> error: use of class template 'Serializer' requires template
> arguments; argument deduction not allowed in non-static class member
> Sagt der Compiler, und wird damit wohl recht haben.

Ja das hat er wohl

noch irgendeine Idee wie ich um die decltypes herum kommen?

von Ntldr -. (ntldr)


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

von cppbert3 (Gast)


Lesenswert?

sieht gar nicht so schlecht aus - Danke für das Beispiel

von Al Fine (Gast)


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?

von Al Fine (Gast)


Lesenswert?

Antwort: Weil das Programm syntaktisch nicht valide ist, und deshalb 
undefined.

von cppbert3 (Gast)


Lesenswert?

Al Fine schrieb:
> Antwort: Weil das Programm syntaktisch nicht valide ist, und
> deshalb undefined.

Wenn es syntaktisch nicht valide wär würde es nicht kompilieren :)

von Al Fine (Gast)


Lesenswert?

Ja, VC++ findet den Fehler ja auch...

von mh (Gast)


Lesenswert?

Al Fine schrieb:
> Antwort: Weil das Programm syntaktisch nicht valide ist, und deshalb
> undefined.

Du meinst semantisch?

Al Fine schrieb:
> Ja, VC++ findet den Fehler ja auch...

Welchen Fehler findet denn der VC++ bei dir? Was der msvc auf godbolt 
ausspuckt ist wenig hilfreich.

von Al Fine (Gast)


Lesenswert?

print() nimmt da noch rvalue-referenzen als Argument. Dass das Unsinn 
ist, mal beiseite. clang und gcc kompilieren das, printen aber den float 
zuerst!

https://gcc.godbolt.org/z/d8eYfv

von Al Fine (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.