Variadic Pack entpacken



  • hiho

    folgender code compiliert nicht:

    #include <utility>
    
    template<typename T>
    void g(T&& x)
    {
      (void)x;
    }
    
    template<typename... args_t>
    void f(args_t&&... args)
    {
      // init stuff
      g(std::forward<args_t>(args))...;
      // cleanup stuff
    }
    

    anscheinend kann man packs nicht so ohne kontext entpacken. ich kenne die standard-methode, dass man eine funktion überlädt, die einen (einzelnen) head und einen (variadischen) tail hat. dann macht man immer was mit dem head und den rest nutzt man für tail-recursion.
    die sache hier ist, dass ich erst zeug initialisieren und nachher wieder aufräumen muss. um den obigen ansatz anwenden zu können, müsste ich eine hilfsfunktion machen, was ich nicht schön fände.

    gibt es eine elegantere möglichkeit, das obige hier zum laufen zu bringen?



  • -   g(std::forward<args_t>(args))...;
    +   g(std::forward<args_t>(args)...);
    


  • funktioniert leider nicht, weil g ja nur 1 argument akzeptiert. ich möchte ja sowas wie g(arg1); g(arg2); ... g(argn); generieren.



  • Beachte den Fall für den es sonst keine weiteren Parameter mehr gibt.

    Ich nenne es den Anker.



  • Ah, sorry, nicht richtig aufgepaßt.

    Wie wäre es damit:

    template <typename... ArgsT>
        void discard(ArgsT&&...)
    {
    }
    
    template <typename... ArgsT>
        void f(ArgsT&&... args)
    {
        // init stuff
        discard((g(std::forward<ArgsT>(args)), 1)...);
        // cleanup stuff
    }
    

    Meines Wissens ist aber die Auswertungsreihenfolge undefiniert; wenn dir das wichtig ist, mußt du halt denselben Trick mit einer Initialisierungsliste anwenden.


  • Mod

    (g(std::forward<args_t>(args)), ...);
    

  • Mod

    Arcoth schrieb:

    (g(std::forward<args_t>(args)), ...);
    

    Bin ich eigentlich der Einzige, der der Ansicht ist, dass die Klammersetzung bei der Expansion von unären folds verkehrt ist?

    (E op ...)
    

    Dürfte die Schreibweise sein, die man üblicherweise bevorzugen möchte. Das führt aber zu

    E_1 op (... op (E_N-1 op E_N))
    

    es wird also so geklammert, als ob op rechtsassoziativ wäre. Allerdings sind fast alle binären Operatoren (ausser den Zuweisungsoperatoren) linksassoziativ. Die natürliche Schreibweise

    (E op ...)
    

    führt also nicht zu

    E_1 op E_2 op ... op E_N
    

    (ausser bei Zuweisungsops).

    Im Falle des (eingebauten) Kommaoperators ist es letzlich egal, weil die Auswertungsreihenfolge von der Klammersetzung nicht beeinflusst wird, und viele der interessanten Operatoren sind kommutativ (abgesehen von Überläufen etc.).


  • Mod

    Die Ellipsis steht für den "Rest" der Berechnung. In diesem Sinne ist x + ... äquivalent zu x_1+f(x_2,,x_n)=x_1+(+(xn1+xn))x\_1 + f(x\_{2}, \cdots, x\_n) = x\_1 + \Big( \cdots + (x_{n-1} + x_n) \cdots \Big).

    Edit:

    viele der interessanten Operatoren sind kommutativ (abgesehen von Überläufen etc.).

    Ja, aber sind nicht genauso viele es nicht? Addition hat Subtraktion, Multiplikation hat Division; es gibt logische Operatoren (wegen SCE nicht praktisch kommutativ, aber prinzipiell), aber im Gegensatz dazu Modulo und Shifts..


  • Mod

    Arcoth schrieb:

    Die Ellipsis steht für den "Rest" der Berechnung. In diesem Sinne ist x + ... äquivalent zu x_1+f(x_2,,x_n)=x_1+(+(xn1+xn))x\_1 + f(x\_{2}, \cdots, x\_n) = x\_1 + \Big( \cdots + (x_{n-1} + x_n) \cdots \Big)

    Ist schon klar. Nur ungefähr so intuitiv wie die Deklarationssyntax in C - bei Parameterpacks will ich ja gerade nicht rekursiv denken müssen.

    Arcoth schrieb:

    viele der interessanten Operatoren sind kommutativ (abgesehen von Überläufen etc.).

    Ja, aber sind nicht genauso viele es nicht? Addition hat Subtraktion, Multiplikation hat Division; es gibt logische Operatoren (wegen SCE nicht praktisch kommutativ, aber prinzipiell), aber im Gegensatz dazu Modulo und Shifts..

    Genau. Ich wollte zeigen, dass mir bewusst ist, dass das Expansionmuster nicht in jedem Fall eine spielt, um diesem Einwand zuvorzukommen.


  • Mod

    Ich kann mich erinnern, das schon einmal recherchiert zu haben. Die ersten paar fold expression proposals schlagen nämlich deine Semantik vor, aber irgendwo gibt es plötzlich einen Umschwung. Ich habe aber nicht rausgefunden, was ihn bewirkt hat.


Anmelden zum Antworten