2013-07-18 14 views
11

2003 - ja, - Vandervoorde und Josuttis schrieben dies in ihrem Buch "C++ Vorlagen" (S. 40).:Warum ist double als Template-Parameter vom Typ nicht zulässig?

Nicht in der Lage Gleitpunktliterale (und einfache Konstante variabel zu verwenden Punktausdrücke) als Vorlagenargumente hat historische Gründe. Da es keine schwerwiegenden technischen Probleme gibt, kann dies in zukünftigen Versionen von C++ unterstützt werden.

Aber dies immer noch nicht funktioniert, auch unter C++ 11:

template<double D> //error 
void foo() {} 

Warum wurde dies nicht hinzugefügt?

+11

Da Gleitkommazahlen Gleichheit ein rutschig Ich bin mir nicht sicher, wie sie sagen können: "Es gibt keine ernsthaften technischen Herausforderungen." Ich denke eher, das wäre voller Gefahren –

+0

@ ErnestFriedman-Hill: Das scheint wie die Grundlage einer Antwort für mich. –

+0

Wir beschäftigen uns jedoch regelmäßig mit Gleichstellungsproblemen im Laufzeitcode. Die gleichen Einschränkungen würden für ihre Verwendung in Vorlagen gelten ... Ich sehe keinen guten Grund, sie nur zur Laufzeit zu behalten. –

Antwort

10

Ich hatte immer angenommen, dass es mit übereinstimmenden Implementierungen zu tun hatte. Wie sind diese beiden Instanzen gleich oder verschieden:

template class foo<10./3.> 
template class foo<1./3 * 10.> 

Sie können die gleiche doppelter Genauigkeit Darstellung nicht erzeugen, so dass der Compiler könnte von ihnen als verschiedene Klassen denken. Dann könnten Sie sie einander nicht zuweisen usw.

5

Bei der Verwendung von Gleitkommazahlen gibt es viele Probleme mit Rundung und Gleichheit. Aus der Sicht des Normalisierungskomitees müssen Sie sicherstellen, dass zwei Programme dasselbe auf mehreren Compilern ausführen. Daher müssen Sie sehr genau angeben, was das Ergebnis der Fließkommaoperation ist. Wahrscheinlich hatten sie das Gefühl, dass die IEEE-754-Norm nicht präzise genug ist ...

Es geht also nicht darum, ob es umsetzbar ist oder nicht, sondern um genau welches Verhalten wir haben wollen.

Beachten Sie jedoch, dass constexpr Gleitkommawerte akzeptiert. Dies reicht normalerweise für die Berechnung der Kompilierzeit aus.

7

Lets auf den folgenden Code aussehen:

template<double D> int f(){ 
    static int i=0; 
    ++i; 
    return i; 
} 

... 

#define D1=... 
#define D2=... 
cout << f<D1>()<<endl; // returns 1 
cout << f<D1-D2+D2>()<<endl; // may return 1 or 2, depending on many things 

See, D1-D2+D2 für einige Werte zu D1 gleich sein können, aber für andere nicht gleich.

Noch wichtiger ist - sie können gleich sein oder nicht abhängig von den Rundungs ​​Einstellungen

Und schließlich können sie gleich oder nicht, je nach Compiler/Architekturen/vielen anderen Dingen sein.

Der Punkt ist, Floating-Point-Operationen sind nicht gut genug definiert für die Vorlagennutzung (sie gut definiert ist, aber es gibt viele mögliche Abweichung von verschiedenen Optionen abhängig)

+0

"abhängig von Einstellungen" ist kein Grund. 'sizeof (Foo)' kann auch von Einstellungen abhängen, ist aber eindeutig erlaubt. – MSalters

+1

Ja, aber die Einstellungen für 'sizeof' werden zur Kompilierzeit ausgewertet, und die Vorlagen werden auch zur Kompilierzeit ausgewertet. Rounding-Einstellungen können sich dagegen zur Laufzeit ändern. Dies führt zu einem Fall, in dem zwei Gleitkommazahlen exakt gleich sind (bei den Einstellungen für die Laufzeit-Rundung), aber ihre jeweiligen Schablonen sind unterschiedlich (da die Berechnung, die sie erstellt haben, unterschiedliche Werte zur Kompilierungszeit ergeben hat). Wenn Sie in meinem Beispiel 'D1-D2 + D2' zur Laufzeit berechnet haben, können Sie genau' D1' erhalten, aber die Vorlagen werden immer noch auf verschiedene Funktionen ausgewertet. – rabensky

+0

Ihr Beispiel scheint seltsam. "Kann 1 oder 2 zurückgeben". D wird in der Funktion nicht einmal verwendet. Was vermisse ich? –

Verwandte Themen