In dem neuen C++ Standard wurde eine alternative Syntax für Funktionen eingeführt. Diese erlaubt den Datentyp des Rückgabewertes am Ende des Funktionskopfes zu schreiben.
// übliche Schreibweise float add(float a, float b); // alternative Schreibweise auto add(float a, float b) -> float;
Über die Bedeutung des Schlüsselwortes auto habe ich bereits geschrieben. In diesem Fall sorgt es dafür, dass der Kompiler die Deklaration auch solche erkennt. Für mich erscheint es an dieser Stelle überflüssig, aber ich vermute, dass der Grund auch an der Abwärtskompatibilität liegt (das ständige Übel…).
Was bringt die neue Syntax überhaupt? Übersicht!
Jeder kennt ähnliche Bilder bei Klassen-Deklarationen.
void setPos(math::vec3 p) {pos =p;} const math::vec3& getPos() const { return pos; } virtual bool interactionTest(math::vec3 point) = 0; size_t getId() const { return id;}
Die Methodennamen sind über das ganze Blickfeld verstreut, so dass man sich anstrengen muss bis man die gefunden hat, die man gesucht hat.
Mit der neuen Schreibweise sind die Methodennamen an einer Linie ausgerichtet.
auto setPos(math::vec3 p) -> void {pos =p;} auto getPos() const -> const math::vec3& { return pos; } virtual bool interactionTest(math::vec3 point) = 0; auto getId() const -> size_t { return id;}
Naja, fast. Bei virtuellen Methoden scheint die neue Syntax nicht zu funktionieren, zumindest führt sie in VS 2012 zu Kompiler-Fehlern.
Die neue Syntax erlaubt auch einige Sprachkonstrukte, die vorher nicht möglich waren.
Als Beispiel betrachten wir eine Reihe von überladenen Funktionen.
int add(int a, int b) { return a+b; } long long add(long long a, int b) { return a+b; } int add(int a, short b) { return a+b; } double add(int a, double b) { return a+b; }
Dieser Haufen an Funktionen lässt sich im Prinzip durch ein Template vermeiden.
template <class A, class B> double add(A a, B b) { return a+b; }
Es dabei aber ein Problem. Der Datentyp des Rückgabewertes ist nicht nur fest, er muss auch noch alle anderen Datentypen abdecken, was zu einem double oder long double führt (bzw. Klassen als Argumente ausschließt). Will man beispielsweise nur mit Integern rechnen, hat wird es eine unschöne Angelegenheit. Ganz davon abgesehen, dass noch ein implizites Typcasting durchgeführt wird.
In C++11 kann man mit decltype(variable) den Datentyp einer Variable bestimmen. So könnte man sich denken, das Template folgendermaßen umzuschreiben.
template <class A, class B> decltype(a+b) add(A a, B b) { return a+b; }
Das funktioniert aber nicht, weil der Datentyp von a bzw. b erst nach decltype(a+b) feststeht. Erst mit der neuen Schreibweise wird das Problem gelöst.
template <class A, class B> auto add(A a, B b) -> decltype(a+b) { return a+b; }
Ich selbst weiß noch nicht so recht, ob ich die neue Syntax benutzen soll. Möglicherweise in kleineren Projekten um zu schauen, ob sich wirklich lohnt…