Go Down

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

Doc_Arduino

Aug 22, 2019, 05:37 pm Last Edit: Aug 22, 2019, 05:59 pm by Doc_Arduino
Hallo,

ich treffe in letzter Zeit vermehrt auf das Problem das ich Standardfunktionen laut Buch auf dem avr nicht verwenden kann. Was macht ihr dann?

Aktuell möchte ich ein Funktionstemplate erweitern und muss dafür den Datentyp ermitteln. Dafür bräuchte ich typeid. Kennt er aber nicht. include typeinfo ist auch nicht bekannt.

Für typeid erhielt ich die Fehlermeldung "cannot use 'typeid' with '-fno-rtti'"
Das konnte ich in der platforms.local.txt mit der Option -frtti beheben.

Allerdings weiß ich nicht woher ich das Includefile typeinfo bekomme?

Code: [Select]

include <typeinfo.h>

int a = 1;

void setup(void) {
  Serial.begin(9600);
  
  if ( typeid(a) == typeid(int) ) {
    Serial.println("int");
  }
  else {
    Serial.println("kein int");
  }
}

void loop(void) {
 
}

Das Vorhaben ist zwischen Ganzzahl und Fließkomma unterscheiden zu können.
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

Das gehört zur C++ std Lib, die steht, wie auch die stl, leider für AVR nicht zur Verfügung.

ARM und ESP Kompiler sollten die dabei haben.
Ob man die da klauen kann?


#include <typeinfo.h>
#include <typeinfo>

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

Quelle: Joseph Joubert

Serenifly

Quote
Das Vorhaben ist zwischen Ganzzahl und Fließkomma unterscheiden zu können.
Das geht mit Templates auch zur Compilezeit:

Code: [Select]

template<typename T, typename U>   //Typen ungleich, gibt 0 zurück
struct is_same
{
  enum { value = 0 };
};

template<typename T>   //Typen gleich, gibt 1 zurück
struct is_same < T, T >
{
  enum { value = 1 };
};

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

  int a = 1;

  if (is_same<int, decltype(a)>::value || is_same<long, decltype(a)>::value)
    Serial.print("Ist ein Integer");
  else
    Serial.print("Ist kein Integer");
}

void loop(void)
{
}


Genaugenommen müsste man per Hand auf alle Integer-Datentypen vergleichen, aber es geht um das Prinzip


In der STL ginge das natürlich einfacher:
https://en.cppreference.com/w/cpp/types/numeric_limits/is_integer

Doc_Arduino

 Hallo,

immer wieder die fehlende STL.  :smiley-confuse:   Ja die ist/kann auf einem AVR Speicher fressend sein, aber wenn man genügend RAM hat und mit bedacht bestimmte STL Funktion nutzen möchte warum nicht. So mein Gedanke dazu.

Auf der Platte im ESP Pfad liegt eine typeinfo Datei.
Ich habe diese einmal hierhin kopiert. Ich weiß ehrlich gesagt nicht wo die richtig hingehört.
C:\avrToolchain\avr-gcc-9.2.0-mingw64-selfmade\lib\gcc\avr\9.2.0\include\
Ich erhalte eine include expression. Sie wird nicht gefunden.
Code: [Select]

"C:\\avrToolchain\\avr-gcc-9.2.0-mingw64-selfmade/bin/avr-g++" -c -g -Os -w -std=gnu++17 -fno-exceptions -fpermissive -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -frtti -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -fno-sized-deallocation -fconcepts "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\mega" "C:\\Users\\Worker\\AppData\\Local\\Temp\\arduino_build_255490\\sketch\\typeid_typeinfo.ino.cpp" -o nul
In file included from C:\Users\user\AppData\Local\Temp\arduino_modified_sketch_432956\typeid_typeinfo.ino:1:
c:\avrtoolchain\avr-gcc-9.2.0-mingw64-selfmade\lib\gcc\avr\9.2.0\include\typeinfo:34:10: fatal error: exception: No such file or directory
   34 | #include <exception>
      |          ^~~~~~~~~~~


Serenifly. Dein Sketch kompiliert in deiner Arduino IDE? Weil decltype benötigt laut meines Wissens auch die include typeinfo.  :o
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,

jetzt bin ich überrascht. Der Arduino IDE default compiler kennt decltype. Mein avr-gcc 9.2 kennt das nicht.  :o
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

#5
Aug 22, 2019, 07:53 pm Last Edit: Aug 22, 2019, 07:54 pm by Serenifly
decltype ist ein C++11 Schlüsselwort und nicht Teil irgendwelcher Bibliotheken/Header

Decltype wird zur Compilezeit evaluiert. Typeinfo ist eine Laufzeit Sache. Deshalb der Kram mit RTTI (run time type information).

Die GCC Alternative ist typeof():
https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Typeof.html

Doc_Arduino

Hallo,

ich erhielt immer solchen Mist. Auch beim Gegencheck mit Zaks 9.1.0 avr-gcc.
Code: [Select]

decltype.ino.elf.vBWGvk.ltrans0.ltrans.o:(.rodata+0x7): undefined reference to `vtable for __cxxabiv1::__class_type_info'
decltype.ino.elf.vBWGvk.ltrans0.ltrans.o:(.rodata+0x13): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
decltype.ino.elf.vBWGvk.ltrans0.ltrans.o:(.rodata+0x2a): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'


Dann habe ich die Compileroption -frtti rausgenommen und es kompiliert auch mit dem 9.1 und 9.2. Compiler wieder.

Ich werde mit decltype weitermachen.  :)

Ich danke dir.
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

Das oben würde auch ohne decltype gehen wenn man das wiederum in ein Template packt und einfach den Typ an is_same durchreicht :)

Doc_Arduino

 Ich rätsel zur Zeit noch wie dein obiger Sketch überhaupt funktioniert.

Ich komme mit den beiden Templates noch nicht mit.
Das Erste hat 2 Datentypen als Parameter, aber T und U werden nicht genutzt.
Das Zweite Template hat nur einen Datentyp als Parameter, wird doppelt übergeben aber intern wiederum nicht genutzt. Und wie man mittels 0 und 1 zwischen int und long unterscheiden kann weiß ich auch nicht. Tut mir leid.



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

#9
Aug 22, 2019, 09:04 pm Last Edit: Aug 22, 2019, 09:18 pm by Serenifly
T und U sind nur dazu da um zu erkennen welche Datentypen man übergibt. T und U sind zwei verschiedene Datentypen. Wenn also die beiden übergebenen Datentypen gleich sind wird das nicht verwendet. Sondern das andere wo beide T sind

Das enum mit 0 und 1 kann man dann mit if (... ::value) auswerten um festzustellen welche Version der Compiler verwendet hat.

Wenn du es schöner machen willst dann kannst du noch den bool() Operator überladen. Dann braucht man das nicht explizit hinschreiben. So:
Code: [Select]

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

operator bool() {
return false;
}
};

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

operator bool() {
return true;
}
};

Code: [Select]

if (is_same<int, decltype(a)>() || is_same<long, decltype(a)>())

Doc_Arduino

Ein Licht geht auf. Die Mannigfaltigkeit der Syntaxkombination treibt mich nochmal in den Wahnsinn. Immer wieder faszinierend angewandte Grundlagen in neuen Kombinationen zu sehen.
Danke für das Bsp. und Erklärung.
Jetzt muss ich mal in Ruhe überlegen wie du das mit dem durchreichen ohne decltype meinst ....
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

#11
Aug 22, 2019, 09:46 pm Last Edit: Aug 22, 2019, 09:49 pm by Serenifly
Ich meinte ein Funktions-Template in diesem Fall. Kein Klassen-Template

Header namens Templates.h anlegen:

Code: [Select]

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

  operator bool() {
    return false;
  }
};

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

  operator bool() {
    return true;
  }
};

template<typename T>
bool is_integer(T value)
{
  return is_same<int, T>() || is_same<long, T>();
}


Dann:
Code: [Select]

#include "Templates.h"

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

  int a = 1;

  if (is_integer(a))
    Serial.print("Ist ein Integer");
  else
    Serial.print("Ist kein Integer");
}

void loop(void)
{
}


Und wie gesagt müssen eigentliche alle Integer Typen in diese Oder-Verknüpfung damit es richtig geht

Doc_Arduino

Hallo,

ganz ehrlich, so schnell wäre ich nicht darauf gekommen. Die Template Denkweise ist schon anders aber verschachtelt nochmals komplizierter. Das es wirklich ohne decltype machbar ist konnte ich mir nicht wirklich vorstellen. Dachte immer noch irgendwie muss man doch den Typ vorher ermitteln um dann vergleichen zu können. Danke das du mir es verraten hast.   :)
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

#13
Aug 23, 2019, 01:10 am Last Edit: Aug 23, 2019, 01:10 am by combie
Quote
Die Template Denkweise ist schon anders aber verschachtelt nochmals komplizierter.
Ich glaube, es ist noch viel dramatischer, als du dir jetzt schon vorstellen kannst....

Mit geraumer Verspätung, die C++ Templates waren schon längst in der Welt, hat irgend einer gemerkt, dass die Template Geschichte "Turing vollständig" ist.
Die "Turing Vollständigkeit" war wohl niemals Teil des Plans.
Aber dennoch, war das wie ein Dammbruch.

So haben wir jetzt in C++ sowas wie eine zweite Sprache, in der wir funktionale (Sub)Sprachen definieren und zur Kompilezeit ausführen können.

(War das richtig formuliert? denn ganz sattelfest bin ich da noch nicht)


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

Quelle: Joseph Joubert

Serenifly

Der eigentliche Witz ist dass von dem Code kaum was ausgeführt wird. Der Compiler löst das auf und setzt direkt das Ergebnis ein.

Bei anderen, größeren Template-Funktionen sieht man auch schön wie die als Code Generatoren arbeiten. Immer wenn man einen weiteren Datentyp verwendet steigt der Verbrauch an Flash, weil eine weitere Funktion erzeugt werden muss.

Go Up