Mal wieder ein grundlegendes Thema für die Template-Gurus:
Ich würde über Templates eine Klasse definieren wollen, die für uint8_t bis uint64_t gültig ist, also für ganzahlige Typen, aber nicht für Fließkommatypen (float/double).
Im Moment fehlt mir die Idee, wie ich die Fließkommatypen ausschließen könnte.
Dann static_assert verwenden um einen Fehler auszulösen
Auf die Schnelle schaffe ich es aber nicht das zusammen zum Laufen zu bekommen. z.B. meint der Compiler die constexpr Funktion wäre nicht konstant wenn ich sie in static_assert einsetzen will
#include "Templates.h"
template <typename T>
class Test
{
public:
T data;
static_assert(is_integer<T>(), "Fehler. Keine Gleitkommazahlen erlaubt");
};
void setup()
{
Test<int> test1;
Test<float> test2;
}
void loop()
{
}
Mit Klassen scheint der Compiler das also wirklich alles zur Compile-Zeit zu schaffen. Wird auch ein Grund sein weshalb so viele dieser Hilfs-Templates als Strukturen ausgeführt sind
Also quasi erstmal für alle allgemeinen Typen ein Template mit false als Rückgabewert und dann über die spezialisierten Templates das true einrichten.
Das ist sicher eine klare Ansage.
Da habe ich ja mit meiner Frage, die noch nichtmal einen aktuellen praktischen Hintergrund hatte, einiges los getreten.
Das ist aber etwas, was mir hier gefällt. Auch auf solche Fragen bekommt man wertvolle Antworten, aus denen man viel lernen kann.
Ja. Da wird ausgenutzt dass bei der Auflösung der Templates die am meisten spezialisierte Variante genommen wird.
Schöne Lösung die die Auflistung der verschiedenen Datentypen etwas übersichtlicher macht
Da habe ich ja mit meiner Frage, die noch nichtmal einen aktuellen praktischen Hintergrund hatte, einiges los getreten.
Das ist aber etwas, was mir hier gefällt.
Mir auch...
Ich bin wahrlich bei dem Thema noch nicht sattelfest und darum dankbar für solche Anlässe.
Das ist sicher eine klare Ansage.
So war es gedacht.
Schöne Lösung die die Auflistung der verschiedenen Datentypen etwas übersichtlicher macht
ich schaue mir das schon eine Weile an. Aber ich weiß überhaupt nicht wie ich das praktisch nutzen soll?
Was mache ich denn dann mit den hier erstellen Objekten test1 bzw. t? :o
Wenn Du ein Klassentemplate bauen willst, dass für alle ganzzahligen Typen char/byte bis unsigned long gültig sein soll, aber nicht für Fließkommazahlen.
Also z.B. Eine Zahl mit Min- und Maxgrenzen. Braucht keiner, mir fällt nur gerade nichts sinvolles ein.
ich schaue mir das schon eine Weile an. Aber ich weiß überhaupt nicht wie ich das praktisch nutzen soll?
Was mache ich denn dann mit den hier erstellen Objekten test1 bzw. t? :o
Was du damit machen kannst.....
Angenommen, manche Dinge würden nur mit bestimmten Typen Sinn machen....
z.B. ein Array Index, der darf nie negativ werden.
Und du möchtest den Typ des Index flexibel halten. Per Template.
Also uint8_t usw erlauben
Aber int usw verbieten.
Und float würde ebenso sinnfrei sein.
Du hättest 3 Möglichkeiten...
Die Gefahr aussitzen
Zur Laufzeit auf index<0 abfragen und einen Fehler melden, Programm abbrechen.
Oder diese Type Traits verwenden und es dir schon vom Kompiler um die Ohren hauen lassen
Doc_Arduino:
Was mache ich denn dann mit den hier erstellen Objekten test1 bzw. t?
Was man halt so mit Objekten macht
Es ging darum einen Compiler-Fehler zu erzeugen wenn man die Klasse in einer bestimmten Weise verwendet. Man kann so z.B. auch verhindern dass jemand riesige Arrays erzeugt.
Ich sage einmal vorsichtig langsam dämmerts. Also die Datentypüberprüfung selbst ist mir schon klar. Nur das weiter anwenden/einbauen daran scheitert es noch, habe eine Denkblockade. Vielleicht löst die sich noch übers WE.
Also ganz grob würde ich mir das bei einer Indexklasse so vorstellen:
template<typename T>
class Index
{
public:
Index() {
static_assert(not is_unsigned<T>(), "Error, kein gültiger Indextyp");
}
T getIdx() {return idx;}
void setIdx(T val) {idx = val;}
void incIdx() { idx++;}
void decIdx() { idx--;}
private:
T idx = 0;
};
Das ist auf die Schnelle aber wohl noch zu kurz gedacht.
Wahrscheinlich müsste man eine ganze Reihe an Operatoren überladen, wie = (lvalue/rvalue), +=, ++/-- (Präfix und Postfix), usw. wenn man diese Klasse wirklich sinnvoll nutzen wollte.
Damit könnte man dann Indexe als uint8_t, uint16_t, ... uint64_t erzeugen.