VC++ 7.1 Bug oder GCC Feature
-
Bis zu welchem Grad muss ein Compiler denn mathematische Gleichungen lösen, um den Template-Parameter herzuleiten? Muss er überhaupt?
Wenn es sich um Integrale Konstanten handelt, und das Ergebnis wiederum zur Initialisierung einer Intgralen Konstanten verwendet wird (Herleitung eines integralen non-type Template-Parameters, Initialisierung einer enum-Konstanten...) muss er die Rechnung zur Compilezeit ausführen. Wenn der VC 7.1 also mit dem DIM + 1 keinen non-type-Parameter vom Typ unsigned herleiten kann, dann ist das ein Fehler.
Was mich jetzt doch sehr irritiert ist, dass selbst der VC 6.0 das Minimalbeispiel übersetzt (nachdem man den beiden non-type-Parametern von Matrix einen Namen gegeben hat).
-
Was mich jetzt doch sehr irritiert ist, dass selbst der VC 6.0 das Minimalbeispiel übersetzt (nachdem man den beiden non-type-Parametern von Matrix einen Namen gegeben hat).
Übersetzt, aber dummerweise vergisst er entsprechenden Code zu generieren
Ah. Diesen Bug kenne ich doch noch aus meinem Loki-Port.
-
Ja toll, endlich unterstützt er partial template specialisation, dafür kann er jetzt Template parameter nicht mehr herleiten. Hab übrigends dein Minimalbeispiel auch mal compiliert:
d:\eengine\test\main.cpp(19) : error C2784: 'Vector<T,A> transform(const Vector<T,A> &,const Matrix<T,dim+1,dim+1> &)' : could not deduce template argument for 'const Matrix<T,dim+1,dim+1> &' from 'Matrix<T,A,B>'
with
[
T=float,
A=4,
B=4
]
d:\eengine\test\main.cpp(10) : see declaration of 'transform'Ich hoffe mal MS wird das in nem Servicepack bereinigen.
-
Ich hoffe mal MS wird das in nem Servicepack bereinigen.
jo, das Ding hat massenhaft Fehler.
-
Wenn es sich um Integrale Konstanten handelt, und das Ergebnis wiederum zur Initialisierung einer Intgralen Konstanten verwendet wird (Herleitung eines integralen non-type Template-Parameters, Initialisierung einer enum-Konstanten...) muss er die Rechnung zur Compilezeit ausführen.
Egal, wie komplex die Berechnung ist? Bei, ... wie nennt man das ... Beispielsweise einem Rekursivem Template müssen ja auch nur 17 "Stufen" ermöglicht werden.
-
HumeSikkins schrieb:
Wenn es sich um Integrale Konstanten handelt, und das Ergebnis wiederum zur Initialisierung einer Intgralen Konstanten verwendet wird (Herleitung eines integralen non-type Template-Parameters, Initialisierung einer enum-Konstanten...) muss er die Rechnung zur Compilezeit ausführen. Wenn der VC 7.1 also mit dem DIM + 1 keinen non-type-Parameter vom Typ unsigned herleiten kann, dann ist das ein Fehler.
Hmm. Und wo sind da die Grenzen? Dass er nicht einmal *1 oder +0 versteht ist natürlich irgendwie blöd, aber muss er auch quadratische Gleichungen etc. lösen können?
-
Hallo,
also ich finde im Standard nichts, dass die Komplexität einer "constant integral expression" einschränkt.Wenn du z.B. den Wert einer enum-Konstante gerne mit einem
Ausdruck a là 5 * 5 * 5 / 4 * 3 % 2 + 7 - 1 * 81 initialisieren willst, nur zu.Selbiges gilt für non-type Template-Parameter.
-
Dass man enum-Konstanten so kompliziert initialisieren kann wie man will, hätte ich eigentlich erwartet. Aber es geht doch hier um die Herleitung und die funktioniert ja genau andersherum:
template<unsigned X> struct Struct {}; template<unsigned Y> unsigned func(Struct<Y * Y * Y>) { return Y; } int main() { return func(Struct<27>()); // 3? }
Nicht, dass wir hier aneinander vorbeireden... muss der Compiler das dann wirklich herleiten können? Und man kann die Komplexität ja noch beliebig erhöhen...
...und wenn ich am Thema vorbeidenke, weist mich bitte auch darauf hin
-
Oha. Nicht du denkst am Thema vorbei sondern ich. Dank des Beispiels weiß ich jetzt aber wenigstens worauf du hinaus willst
eins vorweg:
Dein Beispiel sieht zwar ähnlich aus, ist aber was anderes.Im Urbeispiel wird Dim über den non-type Parameter des Vektors hergeleitet. Danach muss der Compiler nur noch prüfen, ob die Herleitung kompatibel mit den non-type Parametern der Matrix ist. Er hat also den Wert für Dim und muss danach nur noch auf diesen Wert eins addieren.
Dein Beispiel ist anders und funktioniert nicht.
Das hat aber nichts mit der Komplexität des Ausdrucks zu tun.Selbst ein simples:
template<unsigned X> struct Struct {}; template<unsigned Y> unsigned func(Struct<Y + 1>) { return Y; } int main() { return func(Struct<27>()); }
funktioniert nicht, da der Wert von Y nicht hergeleitet werden kann.
Laut Standard kann Y hier niemals hergeleitet werden, da ein Typename wie Struct<Y + 1> niemals für die Herleitung eines non-type-Parameters verwendet wird. Das ist ein sogenannter "nondeduced context".
Der Punkt am Urbeispiel ist, dass der non-type Parameter über den ersten Parameter hergeleitet werden kann und hergeleitet wird. Die nachfolgenden Parameter müssen dann nur noch passen, damit der Aufruf als korrekt durchgehen kann.
PS:
Deswegen ist folgendes Beispiel auch wieder ok:template<unsigned X> struct Struct {}; template<unsigned Y> unsigned func(Struct<Y>, Struct<Y * Y / Y + Y + 1 - 9>) { return Y; } int main() { return func(Struct<5>(), Struct<2>()); }
Hoffentlich habe ich mich nicht verrechnet
-
Ach so. Und ich dachte schon, ich könnte GCC gleich als Algebrasystem missbrauchen... Danke für die Erklärung