Go Down

Topic: Wie kann man typeid nutzen? (Read 519 times) previous topic - next topic

combie

#15
Aug 23, 2019, 12:05 pm Last Edit: Aug 23, 2019, 12:20 pm by combie
Ja... man kann sich schon einen "Code Bloat" mit Templates einfangen.
Mit deiner Methode hier allerdings eher nicht.
Da verschwindest alles.. bis auf 1 ASM Statement, um das Resultat in ein Register zu bekommen.


Übrigens, eine kleine Verbesserung:
> bool is_integer(T value)
Das value erzeugt eine unused Warnung

> bool is_integer(T)
So ist sie weg.


Etwas klarer kann man es evtl so machen
> constexpr bool is_integer(T)
Helfen tuts allerdings nicht, der Kompiler dampft es sowieso ein.

----


Manchmal kann ich mich auch nicht entscheiden, was schöner ist, wenn man denn mal die Wahl hat.


Rekursion zur Kompilezeit:
Hier mal eine gefundene Fakultätsberechnung als Template Variante, und umgebaut zu einer constexpr Funktion.
Mir erscheint die Funktion irgendwie "intuitiver".

Irgendwelche Unterschiede im generierten Code gibt es natürlich nicht.
Zumindest solange dort Literale/Konstanten verwendet werden.
Mit Variablen funktioniert die Templatevariante nicht, und die Funktion kann einem dann den Stack überfluten.



Code: [Select]
#include <Streaming.h>

// -------------------

template <int N>
struct Factorial
{
  enum { value = N * Factorial<N-1>::value };
};
 
template <>
struct Factorial<0>
{
  enum { value = 1 } ;
};

// -------------------


constexpr int fakultaet(const int n)
{
  return 0 == n ? 1 :  n * fakultaet(n-1);
}

// -------------------



void setup()
{
  Serial.begin(9600);
  Serial << "Start " << __FILE__ << endl;

  Serial << Factorial<5>::value  << endl;
  Serial << fakultaet(5)         << endl;
}

void loop()
{
}
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Serenifly

Quote
Übrigens, eine kleine Verbesserung:
> bool is_integer(T value)
Das value erzeugt eine unused Warnung
Dachte ich mir auch erst :o Aber ich verwende Visual Micro und da wird es nicht angemeckert :o Keine Ahnung was da abläuft.
Die Variable zu benennen ist aber so oder so überflüssig

combie

Bei mir avr-gcc-9.1.0 mit -std=gnu++17 und -fno-sized-deallocation, ansonsten Arduino Standard
Vielleicht ist das ja etwas pingeliger.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Doc_Arduino

Hallo,

Serenifly, ohne Werbung machen zu wollen, kannst ja einmal meine avr-gcc 9.2. Toolchain probieren?   :)   Wenn die in Atmel Studio funktioniert sollte sie auch in deiner Visual Studio Umgebung funktionieren.

Templates. Mit selbst gebauten einfachen Funktions- und Klassentemplates komme ich mittlerweile gut klar denke ich. Fremde geschachtelte sind wie immer so eine Sache, wie mit allen fremden Code. Aber mit der prima Erklärung ist das Rätsel gelöst wurden.  

Mit der Turing Fähigkeit kämpfe ich immer noch. Zur Zeit ist es bei mir so. Mache ich aus einer Klasse ein Klassentemplate mit dem Hintergrund universell zu sein, folgt einhergehend automatisch diese wundersame Optimierung im RAM/Flashverbrauch. Mache ich das Template mit dem Hintergrund RAM/Flash Einsparung gehts schief. Bei meiner MCP23017 Lib gehts deswegen auch nicht weiter. Bei meiner aktuellen Spielerei einer universellen seriellen Ausgabe mit Template statt vielen Funktionsüberladungen gabs schon ziemlich am Anfang diese wundersame magische Optimierung. Kurzum, ich kann es noch nicht steuern. Mir fehlt noch der entscheidende Zauberspruch.  ;)  Ich übe/probiere weiter.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Der Kram war auch fremd. Ist im Prinzip ist das genau das was in ::std implementiert ist:
https://en.cppreference.com/w/cpp/types/is_same
Einfache Sachen kann man sich da manchmal selbst nachbauen wenn man weiß wie es gemacht wird

Das sieht man auch dass die Funktionen eigentlich constexpr sein sollten. Spielt hier aber keine Rolle.


Das von combie stammt von Wikipedia:
https://de.wikipedia.org/wiki/C%2B%2B-Metaprogrammierung
In dem Artikel geht es um das allgemeine Prinzip. Statt ausführbare Programme im klassischen Sinn schreibt man Code der nur anderen Code erzeugt

Doc_Arduino

Hallo,

sehr interessant.  Danke.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Wikipedia hat sicherlich auch erheblichen Einfluss....


> struct Factorial
Stammt aus diesem interessanten Artikel.

Die rekursive Funktion stammt aus einer meiner Experimentserien.



Quote
Hallo,

sehr interessant.  Danke.
Du weißt schon, dass du jetzt die Büchse der Pandora geöffnet hast, oder gerade dabei bist.....?
 :smiley-twist:  :smiley-twist:  :smiley-twist:  :smiley-twist:



Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Doc_Arduino

Du weißt schon, dass du jetzt die Büchse der Pandora geöffnet hast, oder gerade dabei bist.....?
 :smiley-twist:  :smiley-twist:  :smiley-twist:  :smiley-twist:
Ich denke auch, weiß noch nicht wie ich aus der Nummer wieder rauskomme.  Weil eigentlich bin ich noch nicht so weit. Je mehr Quellen man kennt umso mehr Informationen stürzen auf Einen ein.   :)  
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

nach einer Pause und erneuter Betrachtung stellt sich mir eine Frage. Die beiden Funktionen is_same dienen ja nur dazu um zu wissen welche Variante der Compiler verwendet um dann festzustellen ob Datentypen gleich oder unterschiedlich sind. Wofür dient dann das enum und constexpr operator bool? Kann man da nicht nur return false oder true schreiben? Dann wäre es leichter lesbar. Oder muss das so sein wegen der Optimierung zusammen?

statt
Code: [Select]

template<typename T, typename U>
struct is_same
{
  enum { value = 0 };

  constexpr operator bool() {
    return false;
  }
};


template<typename T>
struct is_same <T, T>
{
  enum { value = 1 };

  constexpr operator bool() {
    return true;
  }
};


dann

Code: [Select]

template<typename T, typename U>
struct is_same
{
    return false;
};


template<typename T>
struct is_same <T, T>
{
    return true;
};



Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Seit wann haben Klassen Rückgabewerte? Mit operator bool überlädst du den bool Operator, wodurch man Objekte wie Methoden verwenden kann

combie

#25
Oct 27, 2019, 10:22 pm Last Edit: Oct 27, 2019, 10:45 pm by combie
Quote
Dann wäre es leichter lesbar.
Mittlerweile habe ich die Geschichte etwas weiter entwickelt.
Vielleicht ist diese Variante ja leichter lesbar.
Da findet sich ein is_same ohne  enum, es geht also ohne.

Code: [Select]
template<bool b>
struct bool_type
{
  constexpr operator bool()
  {
    return b;
  }
};

struct true_type   :bool_type<true> {};
struct false_type  :bool_type<false>{};

template<typename T> struct is_floating_point         :false_type{};
template<>           struct is_floating_point<float>  :true_type {};
template<>           struct is_floating_point<double> :true_type {};

template<typename T> struct is_signed             :false_type{};
template<>           struct is_signed<int8_t >    :true_type {};
template<>           struct is_signed<int16_t>    :true_type {};
template<>           struct is_signed<int32_t>    :true_type {};
template<>           struct is_signed<int64_t>    :true_type {};

template<typename T> struct is_unsigned           :false_type{};
template<>           struct is_unsigned<uint8_t > :true_type {};
template<>           struct is_unsigned<uint16_t> :true_type {};
template<>           struct is_unsigned<uint32_t> :true_type {};
template<>           struct is_unsigned<uint64_t> :true_type {};

template<typename T> struct is_integral   :bool_type<is_unsigned<T>()||is_signed<T>()>{};
template<typename T> struct is_arithmetic :bool_type<is_integral<T>()||is_floating_point<T>()> {};

template<typename T, typename U> struct is_same      :false_type{};
template<typename T>             struct is_same<T,T> :true_type {};

template<typename T> struct is_void    :bool_type<(is_same<T,void>())> {};
template<typename T> struct is_nullptr :bool_type<(is_same<nullptr_t,T>())> {};

template<typename T> struct is_const          :false_type{};
template<typename T> struct is_const<const T> :true_type {};

template< typename T> struct is_pointer     : false_type{};
template< typename T> struct is_pointer<T*> : true_type {};


template<typename T>           struct is_array       :false_type{};
template<typename T>           struct is_array<T[]>  :true_type {};
template<typename T, size_t N> struct is_array<T[N]> :true_type {};


Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

Doc_Arduino

Hallo,

nicht böse sein. Ich habe das wegen template, struct und constexpr ... nicht mehr überblickt das es ein Objekt ist und kein Datentyp als Rückgabewert voran steht. Wenn ich template Konstrukte nicht selbst schreibe habe ich immer Probleme beim lesen. Die Pause mit dem Thema tat ihr übrigens.

Ich guck mir das an, nehme auch combies Ausarbeitung gern mit und werde schauen was ich damit wie machen kann. Erstmal muss ich zwischen Integer und Float unterscheiden. Langsam wirds ernst für mein Vorhaben. Bis jetzt war es Vorgeplänkel.  :)



Danke Euch.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

ich habs geschnallt.  :smiley-mr-green:  Das sind Bausteine mit denen man sich noch seine eigenen Funktionen bauen muss. Erste Versuche waren erfolgreich. Meine Leitung ist manchmal auch länger als sie sein dürfte. ;)   Danke nochmal.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Hallo,

ich habe das heute nochmal durchprobiert. Was ich nicht hinbekomme ist die Abfrage auf ein Array und einer Konstante. Frage ich ein Array auf Zeiger ab klappt das, zerfällt ja zu einem Zeiger. Habe char und byte Arrays probiert. Klappt nicht. Übersehe ich irgendwas? Ist ein bestimmter Syntax erforderlich?

Eingebunden wird dein Baustein Code als Header.

Code: [Select]

#include "DataTypesDetection.h"

template<typename T>
bool isArray(T)
{
  return (is_array<T>() );
}

template<typename T>
bool isConst(T)
{
  return (is_const<T>() );
}

void setup(void) {
  Serial.begin(9600);

  //char text[] = "Hallo";
  byte zahlen[4] = {0,1,2,3};
  
  if ( isArray(zahlen[4]) )
    Serial.println("Ist ein Array");
  else
    Serial.println("Ist kein Array");  

  const int k = 1;
  
  if ( isConst(k) )
    Serial.println("Ist eine Konstante");
  else
    Serial.println("Ist keine Konstante");  
      
}

void loop(void) {
  
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

T ist nicht das Gleiche wie const T

Code: [Select]

 if ( isArray(zahlen[4]) )

Da übergibst du ja auch kein Array

Go Up