Forum: PC-Programmierung C++17: Templates, Index zu meinem variadic Parameter unpacking


von cppbert (Gast)


Lesenswert?

Platform: C++17, VS2017 (und GCC)

zum Kompilieren: https://godbolt.org/z/55Yjd578K

Ich hab versucht ein ultra abgespecktes Beispiel zu machen - so
nicht mehr ganz sinnvoll - aber es enthält alle Stellen die für mich 
wichtig
sind

Problem: in der Result::fetch fehlt mir der Index 
[1-sizeof...(OutputTypes)]

hat jemand eine Idee wie man das lösen kann?

Da soll am Ende ein typesafer-rer SQLite Wrapper werden
1
template<typename T>
2
struct Converter;
3
4
template<>
5
struct Converter<int>
6
{
7
    static int value(int index_) { return 12345; /* hier wird normalerweise mit index_ und mehr gearbeitet */ };
8
};
9
10
template<>
11
struct Converter<float>
12
{
13
    static float value(int index_) { return 543.12f; /* hier wird normalerweise mit index_ und mehr gearbeitet */ };
14
};
15
16
// ... es gibt viele weitere nicht primitiv-Typ Spezialisierungen
17
18
template<typename... OutputTypes>
19
struct Result
20
{
21
    template<typename Output>
22
    void fetch(Output& output_)
23
    {
24
        // hier ist normlerweise eine Schleife
25
        // mit Abbruchbedinung - und mehr Kontext
26
27
        output_ = { Converter<OutputTypes>::value(0/*SOLL: 1-n*/)..., };
28
    }
29
};
30
31
int main()
32
{
33
    using MyResult = Result<int, float, int>;
34
35
    // in MyResult::fetch sollte das out_first_ assignment jetzt so aufgeloest werden
36
    //    out_first_ = { Converter<int>::value(1), 
37
    //                   Converter<float>::value(2), 
38
    //                   Converter<int>::value(3) };
39
40
    MyResult my_result;
41
42
    struct Output
43
    {
44
        int a;
45
        float b;
46
        int c;
47
    };
48
49
    Output output;
50
    my_result.fetch(output);
51
52
    return 0;
53
}

von Al Fine (Gast)


Lesenswert?

Along the lines
1
template<typename Output>
2
void fetch(Output& output_)
3
{
4
   int index = 1;
5
   output_ = { Converter<OutputTypes>::value(index++)..., };
6
}

von cppbert (Gast)


Lesenswert?

ich mache das Folding Zeug immer noch zu selten - ist ja nur ein 
Parameter d.h. ganz normal mit Variable

und ich habe jetzt auch eine std::index_sequence Lösung die auch mit 
Template-Parameter funktioniert - falls ich das dann doch mal brauche

von Al Fine (Gast)


Lesenswert?

cppbert schrieb:
> und ich habe jetzt auch eine std::index_sequence Lösung die auch mit
> Template-Parameter funktioniert - falls ich das dann doch mal brauche

Ja, richrig. index_sequence war mir jetzt zu frickelig.

von cppbert3 (Gast)


Lesenswert?

Al Fine schrieb:
> cppbert schrieb:
>
>> und ich habe jetzt auch eine std::index_sequence Lösung die auch mit
>> Template-Parameter funktioniert - falls ich das dann doch mal brauche
>
> Ja, richrig. index_sequence war mir jetzt zu frickelig.

ja das war ein bisschen frickelig

von Al Fine (Gast)


Lesenswert?

cppbert3 schrieb:
> ja das war ein bisschen frickelig

Aber wahrscheinlich immer noch besser als die Old-School iteration mit 
einem Hilfs-template.

von M.K. B. (mkbit)


Lesenswert?

Al Fine schrieb:
> Along the lines
>
>
1
> template<typename Output>
2
> void fetch(Output& output_)
3
> {
4
>    int index = 1;
5
>    output_ = { Converter<OutputTypes>::value(index++)..., };
6
> }
7
>

Ich bin mir hier nicht sicher, ob die Reihenfolge der Ausführung von ++ 
beim Kommaoperator mit folding hier garantiert ist. Sonst könnte man auf 
manchen Compilern falsche Werte bekommen.

von Al Fine (Gast)


Lesenswert?

M.K. B. schrieb:
> Ich bin mir hier nicht sicher, ob die Reihenfolge der Ausführung von ++
> beim Kommaoperator mit folding hier garantiert ist.

Das Komma ist kein Operator. Das ist das Trennzeichen einer "list 
initialization". Ich glaube das Komma ist immer sequenzierend - außer 
bei Funktionsparametern.

Beitrag #6739470 wurde von einem Moderator gelöscht.
von Al Fine (Gast)


Lesenswert?

Essex schrieb im Beitrag #6739470:
> Wie kann man sich mit einer Sprache und solchen Fummeligkeiten nur so
> abplagen?

Ich denke, man braucht - je nach Calling-Convention - weniger Stack, 
wenn man die Werte für die Argumente in beliebiger Reihenfolge berechnen 
kann.

von Wilhelm M. (wimalopaan)


Lesenswert?

Falls Du den Index als compiletime-const brauchst:
1
    template<typename Output>
2
    void fetch(Output& output_)
3
    {
4
        auto r = []<auto... II>(std::index_sequence<II...>){
5
            return Output{Converter<OutputTypes>::value(II)...,};
6
        }(std::make_index_sequence<sizeof...(OutputTypes)>{});
7
        output_ = r;
8
    }

von Wilhelm M. (wimalopaan)


Lesenswert?

Sorry, war nicht genau das, was Du wolltest:
1
    static inline constexpr size_t size() {
2
        return sizeof...(OutputTypes);
3
    }
4
    template<typename Output>
5
    void fetch(Output& output_)
6
    {
7
        output_ = []<auto... II>(std::index_sequence<II...>){
8
            return Output{Converter<OutputTypes>::value(II + 1)...,};
9
        }(std::make_index_sequence<size()>{});
10
    }

von Al Fine (Gast)


Lesenswert?

Wilhelm M. schrieb:
>         output_ = []<auto... II>(std::index_sequence<II...>){
>             return Output{Converter<OutputTypes>::value(II + 1)...,};
>         }(std::make_index_sequence<size()>{});

So ist das c++20, oder?

von cppbert3 (Gast)


Lesenswert?

> Wie kann man sich mit einer Sprache und solchen Fummeligkeiten nur so
> abplagen?

wie kommst du darauf das sich irgendwer abplagt, die non template 
variante hab ich in 5min komplett fertig geschrieben, aber mit der 
template lib bekomme ich das viel kürzer, typesafe und generisch 
erweiterbar, dafür nehme ich dann schon ein bisschen arbeit in kauf, 
klar sieht C, C# und Python einfacher aus aber damit ists dann nicht 
typesafe UND einfach zu nutzen und der End-Anwender sieht diesen Code ja 
auch gar nicht

von Wilhelm M. (wimalopaan)


Lesenswert?

cppbert3 schrieb:
>> Wie kann man sich mit einer Sprache und solchen Fummeligkeiten nur so
>> abplagen?
>
> wie kommst du darauf das sich irgendwer abplagt,

Für manche Leute ist eben alles ein "int", und wenn nicht, dann ist es 
ein "string". Das man Datentypen zur Compilezeit ausrechnen lassen kann, 
ist dann unvorstellbar ...

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.