type deduction fuer nontype template parameters



  • Hallo liebe Community,

    Bevor ich einen Proposal schreibe, moechte ich mich erstmal mit meiner Idee an euch wenden, vielleicht habe ich ja irgendwas wichtiges uebersehen, oder mir faellt noch etwas ein, was ich noch unbedingt brauche. ­čÖé

    Ich schlage vor, type deduction fuer template-Value-Parameter hinzuzufuegen. Das soll zum einen der Vereinfachung dienen, andererseits wird es damit moeglich, Parameter-Packs von Variadic Templates in Value-Parametern zu verwenden. (Sorry, mir ist da keine bessere Formulierung eingefallen, bei Unklarheiten bitte nachfragen ­čśë )

    Syntaxmaessig sieht das dann so aus:

    template <auto T, T Value> // (!)
    struct foo
    {};
    
    template <auto C, auto R, auto... P, R (C::* Ptr) (P...) const> // (!)
    struct bar
    {};
    
    struct baz
    {
        void f() const;
    };
    
    extern int i;
    
    foo<42> f1; // T deduced to `int'
    foo<&baz::f> f2; // T deduced to  `void (bar::*) () const'
    foo<&i> f2; // T deduced to  `int*'
    bar<&baz::f> b; // C deduced to `baz', R deduced to `void', P... deduced to {}
    

    Deduzierte Typparameter koennen nicht explizit angegeben werden. Sie koennen an einer beliebigen Stelle der Parameterliste stehen, muessen allerdings vor ihrer Verwendung definiert sein. Type-Deduction muss, wie bei Funktionsparametern, fuer alle Argumente, in denen sie verwendet werden, erfolgreich sein, damit das Template instanziert werden kann.

    Was haltet ihr davon?
    Vorschlaege? Wuensche? Verbesserungen? :p

    Gruesse,
    Der Kellerautomat


  • Mod

    Erscheint mir etwas zu kompliziert.
    Wie w├Ąre es mit

    template <auto Value>
    struct foo
    {
      // decltype(Value) wenn der Typ ben├Âtigt wird
    };
    
    template <typename T, T* Value> // bei Spezialisierungen taucht der Typ automatisch auf
    struct foo<value> 
    {
    };
    
    template <auto X>
    struct bar;
    
    template <auto C, auto R, auto... P, R (C::* Ptr) (P...) const>
    struct bar<Ptr>
    {
    };
    

    soweit ich das ├╝berblicke, ben├Âtigt man hierf├╝r keine neuen Deduktionsregeln.
    Etwas komplizierter wird es evtl., wenn man auch auto-Parameterpacks haben will.



  • Diese Syntax hatte ich davor. Dass man natuerlich einfach spezialisieren kann, habe ich dabei nicht bedacht.

    Bei struct bar meintest du wohl folgendes, oder?

    template <typename C, typename R, typename... P, R (C::* Ptr) (P...) const>
    struct bar<Ptr>
    {
    };
    

    Deduktionsregeln braucht man hier selbstverstaendlich keine neuen, hier koennen die gleiche wie bei Funktionsparametern zum einsatz kommen. Durch Einschraenkungen, was ein Template-Value-Parameter ueberhaupt sein kann, wird es evtl. sogar etwas einfacher.

    Was meinst du mit auto-Parameter Packs? Inwiefern wuerden sich hier die Regeln unterscheiden?


  • Mod

    Kellerautomat schrieb:

    DBei struct bar meintest du wohl folgendes, oder?

    template <typename C, typename R, typename... P, R (C::* Ptr) (P...) const>
    struct bar<Ptr>
    {
    };
    

    ├Ąh, ja.

    Deduktionsregeln braucht man hier selbstverstaendlich keine neuen, hier koennen die gleiche wie bei Funktionsparametern zum einsatz kommen. Durch Einschraenkungen, was ein Template-Value-Parameter ueberhaupt sein kann, wird es evtl. sogar etwas einfacher.

    Kellerautomat schrieb:

    Was meinst du mit auto-Parameter Packs? Inwiefern wuerden sich hier die Regeln unterscheiden?

    non-type Parameterpacks bestehen gegenw├Ąrtig aus Werten eines einzigen Typs. Es w├Ąre zu ├╝berlegen, ob diese Beschr├Ąnkung beibehalten werden soll

    template <auto... x>
    struct foo;
    
    template <typename... T, T... x>
    struct foo<x...> {};
    // oder
    template <typename T, T... x>
    struct foo<x...> {};
    // ? evtl. k├Ânnte auch beides erlaubt werden
    

    Eine weitere Verallgemeinerung k├Ânnte ggf. auch in Verbindung mit anderen Parameterarten eingef├╝hrt werden, indem eine weitere Kategorie eingef├╝hrt wird, ich nenne sie mal polymorph:
    definiere: ein polymorpher Parameter P wird deklariert durch

    void P
    

    jedes allgemein f├╝r Template-, Typ- oder nicht-Typ-parameter m├Âgliche Argument ist ein zul├Ąssiges Argument f├╝r einen polymorphen Parameter. Innerhalb einer Templatedefinition kann ein polymorpher Parameter nur als Templateargument verwendet werden (einfacheste L├Âsung, die auch mit Aliastemplates kompatibel ist) - an irgendeinem Punkt muss also spezialisiert werden. Damit k├Ânnte dann z.B. ein std::set so modifiziert werden, dass es auch direkt mit Vergleichsfunktionen als Templateargument zurecht kommt.
    Eine gute Idee f├╝r eine allgemeinere Deklaration (und eine Methode, diese in Spezialisierungen vern├╝nftig auseinander zu nehmen) f├╝r Template-template-parameter habe ich allerdings nicht.



  • camper schrieb:

    non-type Parameterpacks bestehen gegenw├Ąrtig aus Werten eines einzigen Typs. Es w├Ąre zu ├╝berlegen, ob diese Beschr├Ąnkung beibehalten werden soll

    template <auto... x>
    struct foo;
    
    template <typename... T, T... x>
    struct foo<x...> {};
    // oder
    template <typename T, T... x>
    struct foo<x...> {};
    // ? evtl. k├Ânnte auch beides erlaubt werden
    

    Ich wuerde sagen, auto... steht fuer ein Parameter-Pack von Werten beliebigen Typs. Wer nur einen Typ haben moechte, der kann ja spezialisieren:

    template <auto...>
    struct foo
    {
        // allg., verschiedene Typen
    };
    
    template <typename T, T... V>
    struct foo<V...>
    {
        // nur ein Typ erlaubt
    };
    

    camper schrieb:

    Eine weitere Verallgemeinerung k├Ânnte ggf. auch in Verbindung mit anderen Parameterarten eingef├╝hrt werden, indem eine weitere Kategorie eingef├╝hrt wird, ich nenne sie mal polymorph:
    definiere: ein polymorpher Parameter P wird deklariert durch

    void P
    

    jedes allgemein f├╝r Template-, Typ- oder nicht-Typ-parameter m├Âgliche Argument ist ein zul├Ąssiges Argument f├╝r einen polymorphen Parameter. Innerhalb einer Templatedefinition kann ein polymorpher Parameter nur als Templateargument verwendet werden (einfacheste L├Âsung, die auch mit Aliastemplates kompatibel ist) - an irgendeinem Punkt muss also spezialisiert werden. Damit k├Ânnte dann z.B. ein std::set so modifiziert werden, dass es auch direkt mit Vergleichsfunktionen als Templateargument zurecht kommt.
    Eine gute Idee f├╝r eine allgemeinere Deklaration (und eine Methode, diese in Spezialisierungen vern├╝nftig auseinander zu nehmen) f├╝r Template-template-parameter habe ich allerdings nicht.

    Wenn ich das richtig verstanden habe, kommt das "weakly specified parameters" aus diesem Proposal recht nahe: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3416.html


Log in to reply