Hi, ich würde gerne abhängig davon, ob ein Typ floating point ist oder
nicht, ein Template spezialisieren: Für Floats soll einfach x*x
berechnet werden, ansonsten x.square():
Über SFINAE werden die einzelnen Overloads aktiviert. Hat den Vorteil,
dass man beliebig weitere Overloads für andere Arten von Typen (z.B.
Integer, Klassen die kein .square() aber operator* haben, ...)
hinzufügen kann, solange die Auswahl immer eindeutig ist. Dies wird
möglich weil die zweite Variante auf die Existenz von .square() prüft,
anstatt einfach alle nicht-float-Typen zu akzeptieren.
Dr. Sommer schrieb:> Über SFINAE werden die einzelnen Overloads aktiviert. Hat den Vorteil,> dass man beliebig weitere Overloads für andere Arten von Typen (z.B.> Integer, Klassen die kein .square() aber operator* haben, ...)> hinzufügen kann, solange die Auswahl immer eindeutig ist. Dies wird> möglich weil die zweite Variante auf die Existenz von .square() prüft,> anstatt einfach alle nicht-float-Typen zu akzeptieren.
Und man braucht keinen C++17 Compiler, sollte das ein Kriterium sein.
"Schöner" is imho trotzdem die von Willhelm gepostete Variante.
Vincent H. schrieb:> Dr. Sommer schrieb:>> Über SFINAE werden die einzelnen Overloads aktiviert. Hat den Vorteil,>> dass man beliebig weitere Overloads für andere Arten von Typen (z.B.>> Integer, Klassen die kein .square() aber operator* haben, ...)>> hinzufügen kann, solange die Auswahl immer eindeutig ist. Dies wird>> möglich weil die zweite Variante auf die Existenz von .square() prüft,>> anstatt einfach alle nicht-float-Typen zu akzeptieren.>> Und man braucht keinen C++17 Compiler, sollte das ein Kriterium sein.> "Schöner" is imho trotzdem die von Willhelm gepostete Variante.
Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu
verwenden?
Vincent H. schrieb:> "Schöner" is imho trotzdem die von Willhelm gepostete Variante.
Wenn sie so ausreichend ist, ja. C++ Programmierer mögen Overloads, weil
man so für alle möglichen Typen unterschiedliches Verhalten definieren
kann anhand relativ komplexer Kriterien, und außerdem noch später
zusätzliche Varianten hinzufügen kann ohne die Original-Funktion zu
ändern. So passiert das auch z.B. in der Standard-Library mit std::hash
und std::begin.
Wilhelm M. schrieb:> Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu> verwenden?
z.B. der GCC-ARM-Embedded (offizieller GCC von ARM) kann C++17 nur
teilweise, und eben kein "if constexpr"...
Dr. Sommer schrieb:> Noch eine Möglichkeit:> [c]#include <utility>> #include <type_traits>>> struct X {> X square () const { return {}; }> };>> template <typename T>> constexpr std::enable_if_t<std::is_floating_point<T>::value, T> square> (const T& a) {> return a * a;> }>> template <typename T>> constexpr decltype (std::declval<const T> ().square ()) square (const T&> a) {> return a.square ();> }
Statt decltype(...) kann man ainfach auto für den Typ der Funktion
schreiben.
constexpr nutzt nichts, da oben die Elementfunktion X::square() nicht
constexpr ist (-> kein constexpr-Kontext).
Dr. Sommer schrieb:> Vincent H. schrieb:>> "Schöner" is imho trotzdem die von Willhelm gepostete Variante.> Wenn sie so ausreichend ist, ja. C++ Programmierer mögen Overloads, weil> man so für alle möglichen Typen unterschiedliches Verhalten definieren> kann anhand relativ komplexer Kriterien, und außerdem noch später> zusätzliche Varianten hinzufügen kann ohne die Original-Funktion zu> ändern. So passiert das auch z.B. in der Standard-Library mit std::hash> und std::begin.>> Wilhelm M. schrieb:>> Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu>> verwenden?> z.B. der GCC-ARM-Embedded (offizieller GCC von ARM) kann C++17 nur> teilweise, und eben kein "if constexpr"...
Wir reden in diesem Unter-Forum über not-embedded, oder?
Dr. Sommer schrieb:> Vincent H. schrieb:>> "Schöner" is imho trotzdem die von Willhelm gepostete Variante.> Wenn sie so ausreichend ist, ja. C++ Programmierer mögen Overloads, weil
oder eben template-Spezialisierungen ...
SFINAE, um eine Funktion aus dem Overload-Set zu entfernen, gehört
eigentlich der Vergangenheit an ... auch wenn concepts noch nicht
generell verfügbar sind, sollte man sich darauf einstellen. Mit C++20
haben wir dieses Mega-Feature!
Wilhelm M. schrieb:> Statt decltype(...) kann man ainfach auto für den Typ der Funktion> schreiben.
Aber dann trifft der Overload auf alle Typen zu, auch z.B. integer, und
führt dann beim Aufruf zum Fehler. Somit wird ein zusätzlicher Overload
für Integer unmöglich gemacht. Das decltype(...) stellt hier sicher,
dass T eine Klasse ist und .square() kennt.
Wilhelm M. schrieb:> Wir reden in diesem Unter-Forum über not-embedded, oder?
Es könnte ja sein dass jemand so etwas auch auf Controllern nutzen will,
da spricht ja nichts gegen.
Wilhelm M. schrieb:> constexpr nutzt nichts, da oben die Elementfunktion X::square() nicht> constexpr ist (-> kein constexpr-Kontext).
X::square ist nicht constexpr, aber eine später hinzugefügte Klasse Y
könnte das als constexpr haben. Dafür ist es sinnvoll vorzusorgen.
Wilhelm M. schrieb:> oder eben template-Spezialisierungen ...
Sind aber etwas lästiger, weil man hier noch eine extra-Hilfsfunktion
braucht die die Unterscheidung macht, man kann nicht direkt SFINAE-mäßig
unterscheiden.
Wilhelm M. schrieb:> auch wenn concepts noch nicht> generell verfügbar sind, sollte man sich darauf einstellen. Mit C++20> haben wir dieses Mega-Feature!
Ja, sag Bescheid wenn es standardisiert und compiler-übergreifend
verfügbar ist.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Statt decltype(...) kann man ainfach auto für den Typ der Funktion>> schreiben.> Aber dann trifft der Overload auf alle Typen zu, auch z.B. integer, und> führt dann beim Aufruf zum Fehler. Somit wird ein zusätzlicher Overload> für Integer unmöglich gemacht. Das decltype(...) stellt hier sicher,> dass T eine Klasse ist und .square() kennt.
Ja, das stimmt. Sorry!
> Wilhelm M. schrieb:>> Wir reden in diesem Unter-Forum über not-embedded, oder?> Es könnte ja sein dass jemand so etwas auch auf Controllern nutzen will,> da spricht ja nichts gegen.
Genau, z.B. auch AVR, wo es geht.
Wilhelm M. schrieb:> Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu> verwenden?
Einige Gründe:
- Es gibt wohl derzeit noch keinen Compiler, der C++17 vollständig
unterstützt: http://en.cppreference.com/w/cpp/compiler_support
- Einige Compiler sind sehr weit von einer auch nur halben Unterstützung
entfernt
- Wer immer auf die aktuellste Software umsteigt, ist zwar ein löblicher
beta-tester, aber wird kommerziell scheitern
- Inkompatible ABIs. Wenn ich z.B. meine C++ Objekte in Python (mit z.B.
swig) einbinden möchte, muss ich den Compiler nehmen, mit dem die Python
Version compiliert wurde. Cpython 3.6 wurde mit MSVC 2015 compiliert.
- Selbes Problem für alle C++ Bibliotheken.
lalala schrieb:> Noch als Anmerkung: Ich denke, dass bald der Stand erreicht ist, das man> von C++11 als universellen Standard ausgehen kann. C++17 sehe ich so ab> 2025.
Das sehe ich ganz und gar nicht so! Aber Prognosen sind immer schwierig,
vor allem, wenn sie die Zukunft betreffen ;-)
Wilhelm M. schrieb:> Das sehe ich ganz und gar nicht so!
Du denkst, das dauert noch länger?
Oder Du denkst wir sind schon da? Dann erzähl mal, welche C++17
Bibliotheken Du verwendest, und wo Du Kunden (außer im
Insolvenzverzeichnis :-)) findest, die glücklich wären, wenn Du C++17
Code/Bibliotheken auslieferst.
Wilhelm M. schrieb:> Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu> verwenden?
Ähm, C++17 ist erst in der DIS-Stage und stellt noch gar nicht "den"
aktuellen offiziellen Standard dar (das ist momentan C++14).
nicht"Gast" schrieb:> Warum nicht ganz Klassisch so?
Übergib mal ein "double" oder einen "int"... Außerdem wäre es schlau die
Referenzen "const" zu machen.
Dr. Sommer schrieb:> nicht"Gast" schrieb:>> Warum nicht ganz Klassisch so?>> Übergib mal ein "double" oder einen "int"... Außerdem wäre es schlau die> Referenzen "const" zu machen.
Jetz hab ichs. Ohne farbigen Code ist der Text vom TE aber auch echt
schwer zu lesen. :)
Sjarne Boustrup schrieb:> Wilhelm M. schrieb:>> Wir haben Ende 2017: welchen Grund sollte es geben, kein C++17 zu>> verwenden?>> Ähm, C++17 ist erst in der DIS-Stage und stellt noch gar nicht "den"> aktuellen offiziellen Standard dar (das ist momentan C++14).
Allerdings gab es keine Einwände zum DIS:
https://herbsutter.com/2017/09/06/c17-is-formally-approved/
so dass nur noch redaktionelle Änderungen vor der eigentlichen
Veröffentlichung als ISO Std. notwendig sind. Also: das was wir momentan
haben IST schon inhaltlich / technisch der offizielle Standard. Und die
Arbeit an C++20 hat schon vor einiger Zeit begonnen.