Forum: Compiler & IDEs C++ Compiler Warnings Template Funktion


von Josh S. (joooooosh)


Lesenswert?

Hallo zusammen,

wie muss eine C++ Template Funktion programmiert werden, damit der 
Compiler keine Warnings mehr auswirft?

Ich habe eine Template Funktion der eine Variable als Referenz übergeben 
wird. Diese Variable wird in der Funktion geändert.

Die Funktion sieht wiefolg aus:
1
  // Klassenvariablen
2
  uint32_t flashAddresse;
3
  uint8_t sektorNummer; 
4
5
  template<class T>
6
  int16_t getAttribute(int16_t ID, T& argpAttribute)
7
  {
8
    switch (ID) {
9
      case FLASHADDRESSE_ID:
10
        if(typeid(argpAttribute) == typeid(flashAddresse)){
11
          argpAttribute = flashAddresse;
12
        }
13
14
        break;
15
      case SEKTORNUMMER_ID:
16
        argpAttribute = sektorNummer;
17
        break;
18
      default:
19
        return NOPARAM_IN_FLASH;
20
    }
21
    return SUCCESS;
22
  }

Dabei gibt der Compiler diese Warnung:

"conversion to 'short int' from 'uint32_t {aka long unsigned int}' may 
alter its value [-Wconversion]"


bei folgender Zeile:
1
argpAttribute = flashAddresse;

Hat irgendjemand eine Idee wie man das programmieren kann ohne dass 
Compiler Warnungen ausgegeben werden?

Viele Grüße

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Josh S. schrieb:
> if(typeid(argpAttribute) == typeid(flashAddresse)){

Warum hier Laufzeit-Typinformationen verwenden? Besser geht's so:
1
if constexpr (std::is_same_v<T, decltype(flashAdresse)>) {

Josh S. schrieb:
> Hat irgendjemand eine Idee wie man das programmieren kann ohne dass
> Compiler Warnungen ausgegeben werden?

Kommt darauf an was du mit den überzähligen Bits machen möchtest... 
sektorNummer enthält 32bit, argpAttribute in deinem Fall anscheinend 
vermutlich 16. Was wenn sektorNummer = 100000 ist? Das passt 
wahrscheinlich nicht in einen short int. Wenn du sicher bist dass der 
Typbereich immer passt, einfach einen Cast einfügen:
1
argpAttribute = static_cast<T> (sektorNummer);

Sicher dass da nicht noch irgendwo Referenzen und Zeiger fehlen? Eine 
Adresse direkt auf einen Wert zuweisen klingt irgendwie falsch.

von Josh S. (joooooosh)


Lesenswert?

Hi Niklas G.

vielen Dank für die schnelle und ausführliche Antwort.

Mit dem Ausdruck
1
if constexpr (std::is_same_v<T, decltype(flashAdresse)>)

funktioniert es denk ich nicht, da die Übergabetypen nicht const. sind 
und somit zur Compilezeit nicht ausgeführt werden können?!

Habe nun folgende Lösung verwendet:
1
  template<class T>
2
  int16_t getAttribute(int16_t ID, T& argpAttribute)
3
  {
4
    switch (ID) {
5
      case FLASHADDRESSE_ID:
6
        if (typeid(argpAttribute) == typeid(flashAddresse)) {
7
          argpAttribute = static_cast<T> (flashAddresse);
8
        }else{
9
          return FALSCHER_TYP;
10
        }
11
        break;
12
      case SEKTORNUMMER_ID:
13
        argpAttribute = sektorNummer;
14
        break;
15
      default:
16
        return NOPARAM_IN_FLASH;
17
    }
18
    return SUCCESS;
19
  }

Hiermit ist der Compiler zufrieden.

Niklas G. schrieb:
> Sicher dass da nicht noch irgendwo Referenzen und Zeiger fehlen? Eine
> Adresse direkt auf einen Wert zuweisen klingt irgendwie falsch.

Die Addresse wird absichtlich einen Wert zugewiesen um Sektor und 
Pagebereich im Flash zu berechnen.

Viele Grüße

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Josh S. schrieb:
> funktioniert es denk ich nicht, da die Übergabetypen nicht const. sind
> und somit zur Compilezeit nicht ausgeführt werden können?!

Hä? Typen sind immer zur Kompile-Zeit fix. Das "if constexpr" und 
"is_same_v" gibt's erst ab C++17, du musst deinen Compiler also ggf. auf 
C++17 einstellen. Für ältere Sprachstandards kannst du es so machen:
1
if (std::is_same<T, decltype(flashAdresse)>::value)
Aber dann muss der Code im if-Block korrekt kompilierbar sein, auch wenn 
er niemals ausgeführt wird.

"typeid" würde ich auf Mikrocontrollern grundsätzlich nicht benutzen 
weil es zusätzlichen Speicher braucht.

Wäre es nicht ggf. clever die "ID" als template-Parameter zu übergeben? 
Die sollte ja sowieso zum Typ passen. Du könntest dann auch anhand der 
ID spezialisieren sodass das switch-case ganz wegfällt und auch der Typ 
kein template-Parameter mehr sein muss; dann kann man die Funktion gar 
nicht mehr falsch aufrufen.

Andererseits - warum überhaupt template-Funktionen? Warum nicht ganz 
simpel:
1
void getFlashAddress (uint32_t a) { flashAddresse = a; }
2
void getSector (uint8_t s) { sektorNummer = s; }

: Bearbeitet durch User
von Josh S. (joooooosh)


Lesenswert?

okay alles klar vielen Dank für die Infos.

Verwende nun
1
if (std::is_same<T, decltype(flashAdresse)>::value)

anstatt "typeid" hinsichtlich des Speichers.


Niklas G. schrieb:
> Andererseits - warum überhaupt template-Funktionen? Warum nicht ganz
> simpel:void getFlashAddress (uint32_t a) { flashAddresse = a; }
> void getSector (uint8_t s) { sektorNummer = s; }

Gute Frage^^ Wollte es halt mit einer Funktion machen.

von Sven B. (scummos)


Lesenswert?

Josh S. schrieb:
> Niklas G. schrieb:
>> Andererseits - warum überhaupt template-Funktionen? Warum nicht ganz
>> simpel:void getFlashAddress (uint32_t a) { flashAddresse = a; }
>> void getSector (uint8_t s) { sektorNummer = s; }
>
> Gute Frage^^ Wollte es halt mit einer Funktion machen.

Ist aber nur aus Coolness-Gründen sinnvoll und hilft weder der 
Lesbarkeit, noch der Performance. ;)

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Sven B. schrieb:
> Ist aber nur aus Coolness-Gründen sinnvoll und hilft weder der
> Lesbarkeit, noch der Performance. ;)

Ja, verschiedene Aspekte in eine Funktion quetschen sind nicht immer so 
sinnvoll. Insbesondere hast du jetzt eine Fehlermöglichkeit eingebaut - 
beim Aufruf könnte man eine nicht existente ID übergeben oder der Typ 
könnte nicht zur ID passen. Diese Fehler bemerkt man erst bei der 
Ausführung; wenn der entsprechende Codeteil aber nur selten ausgeführt 
wird ggf. erst sehr spät. Da ist es besser einfach nur zwei Funktionen 
zu nehmen - nicht existente Funktionen kann man nicht aufrufen, und 
falsche Typen würde der Compiler direkt bemängeln.
Verwirrend ist es für den Leser auch - er sucht den Grund, warum die 
komplexe template-Funktion nötig ist und die zwei einzelnen Funktionen 
nicht ausreichen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.