double als const template parameter



  • Hallo,
    gibt es irgendeine Möglichkeit, folgendes zu realisieren?

    template<double d>
    class foo
    {
    };
    int main()
    {
        foo<1.0> f;
    }
    

    ... Ich verstehe auch nicht, wieso das nicht machbar ist. Was ist der grund hierfür?

    Danke im Voraus.



  • Das was du da machst ist irgend ein Murks. Ich nehme an du möchtest folgendes haben:

    template<typename T>
    class Foo
    {
    	//...
    };
    
    int main()
    {
    	Foo<double> f;
    }
    


  • Ganz einfach, weil laut Standard:

    |1|Fehler: »double« ist kein gültiger Typ für einen Templatekonstanten-Parameter|
    

    Edit: Das "Warum" bekommt man nach ein paar Sekunden googeln:

    http://www.c-plusplus.net/forum/p1214921#1214921



  • Ja, Fließkommazahlen gibt es nicht als non-type template-parameter; der Typ muss integral sein.

    @icarus: Ich glaube, non-type Template-Parameter und Typparameter kann man schlecht verwechseln.



  • Ne, ich schau mir gerade zum ersten Mal template metaprogrammierung an. Und da trifft man gleich mal auf folgendes Bsp.:

    template <int N>
    struct Factorial {
        enum { value = N * Factorial<N - 1>::value };
    };
    
    template <>
    struct Factorial<0> {
        enum { value = 1 };
    };
    
    int main()
    {
        const int x = Factorial<4>::value; // == 24
        const int y = Factorial<0>::value; // == 1
    }
    

    Dann hab ich mich gefragt, ob man als int auch double oder sontwas verwenden kann. Das scheint aber nicht zu gehen. Deshalb die Frage. Geht das nur mit Ganzzahlen, oder kann man es über Umwege auch mit anderen Typen erreichen?



  • Eine Idee wäre, das ganze in einen Bruch umzuschreiben. Möglich wäre es dann, Zähler und Nenner zu übergeben.

    Oder vielleicht das ganze mit Exponentialschreibweise und ganzzahliger Mantisse, die >= 10 sein darf. Also bspw.

    1,4561,456

    wäre

    14561031456 * 10^{-3}

    und du nimmst als Template-Parameter einfach die Mantisse und den Exponent als Ganzzahl.



  • Das sind aber alles Umwege, die sich imo nicht lohnen, um praktisch einsetzbar zu sein. Zudem gibt es ab C++11 Const Expressions, die für dieses Beispiel eingesetzt werden können.



  • Ok.

    @Incocnito: Die Antwort von CStoll hab ich gesehen. Allerdings dachte ich, ich hätte mal ein Proposal gelesen, das soetwas eingeführt werden sollte (kann es aber gerade nicht mehr finden), und es mitterweile irgendwie möglich wäre. Wenn Fließkommazahlen aber wirklich erst zur Laufzeit erzeugt werden können, wäre es ja praktisch unmöglich. Dann frag ich mich aber, an was ich mich da erinnere. 🤡



  • Quatsch, Fließkommazahlen können natürlich auch zur Kompilierzeit erzeugt werden. Oder denkst Du, dass eine Rechnung wie

    const double z = 1.0 + 9.0;
    

    zur Laufzeit ausgeführt wird?


  • Mod

    out schrieb:

    kann man es über Umwege auch mit anderen Typen erreichen?

    Viele Anwendungsfälle können auch durch Verwendung von constexpr-Funktionen gelöst werden.
    Im Übrigen kann eine Gleitkommazahl auch durch eine Integersequenz ausgedrückt werden. Auf die Weise ist auch schon pi per TMP berechnet worden.

    n3337 schrieb:

    14.1 Template parameters [temp.param]
    [...]
    4 A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
    — integral or enumeration type,
    — pointer to object or pointer to function,
    — lvalue reference to object or lvalue reference to function,
    — pointer to member,
    — std::nullptr_t.

    [...]
    14.3.2 Template non-type arguments [temp.arg.nontype]
    1 A template-argument for a non-type, non-template template-parameter shall be one of:
    — for a non-type template-parameter of integral or enumeration type, a converted constant expression(5.19) of the type of the template-parameter; or
    — the name of a non-type template-parameter; or
    — a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
    — a constant expression that evaluates to a null pointer value (4.10); or
    — a constant expression that evaluates to a null member pointer value (4.11); or
    — a pointer to member expressed as described in 5.3.1.



  • camper schrieb:

    Im Übrigen kann eine Gleitkommazahl auch durch eine Integersequenz ausgedrückt werden. Auf die Weise ist auch schon pi per TMP berechnet worden.

    Hey camper, danke! Jetzt hab' ich für den Abend was zu tun! 🙂



  • Den gerade zitierten C++ Standard als Draft gibt es hier:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/

    Nennt sich N3337.pdf und gehört auf jeden Fall in Dein Literatur-Repertoire...



  • Eisflamme schrieb:

    Quatsch, Fließkommazahlen können natürlich auch zur Kompilierzeit erzeugt werden. Oder denkst Du, dass eine Rechnung wie

    const double z = 1.0 + 9.0;
    

    zur Laufzeit ausgeführt wird?

    Ne, hast natürlich Recht. 😉

    Furble Wurble schrieb:

    Den gerade zitierten C++ Standard als Draft gibt es hier:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/

    Nennt sich N3337.pdf und gehört auf jeden Fall in Dein Literatur-Repertoire...

    Stimmt, den aktuellen Draft sollte ich mir mal holen.

    Danke euch allen. 🙂



  • War nicht mal im Gespräch dass sie float/double als non-type Template Parameter erlauben wollen -- eben weil es keinen wirklich guten Grund gibt warum sie nicht erlaubt sind?



  • Könnte es nicht Probleme wegen der Ungenauigkeit geben?
    D.h. wären

    foo<1.0> f;
    

    und

    foo<3.0*(1.0/3.0)> f;
    

    die gleiche Instantiierung?
    Und es müßte geklärt werden, ob +0.0, -0.0 sowie die verschiedenen NAN-Represesentationen als gleich angesehen werden würden (s. den defacto-Standard http://de.wikipedia.org/wiki/Ieee754).



  • Furble Wurble schrieb:

    Den gerade zitierten C++ Standard als Draft gibt es hier:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/

    Nennt sich N3337.pdf und gehört auf jeden Fall in Dein Literatur-Repertoire...

    Nennt sich wohl eher N3376.pdf 🤡



  • cooky451 schrieb:

    Furble Wurble schrieb:

    Den gerade zitierten C++ Standard als Draft gibt es hier:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/

    Nennt sich N3337.pdf und gehört auf jeden Fall in Dein Literatur-Repertoire...

    Nennt sich wohl eher N3376.pdf 🤡

    ¡Ay, caramba! 🙂


  • Mod

    cooky451 schrieb:

    Furble Wurble schrieb:

    Den gerade zitierten C++ Standard als Draft gibt es hier:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/

    Nennt sich N3337.pdf und gehört auf jeden Fall in Dein Literatur-Repertoire...

    Nennt sich wohl eher N3376.pdf 🤡

    n3337 enthält im Gegensatz zu n3376 nur redaktionelle Änderungen gegenüber dem Standard.
    n3376 enthält demgegenüber bereits Änderungen, die ggf. mal in der nächsten Revision des Standards auftauchen werden, ist aber folglich ungeeignet, den gegenwärtig verbindlichen Stand abzubilden.


Log in to reply