C++ Compiler Warnings Template Funktion

#5688185
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
Persönliche Seite #5688190
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.
#5688288
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
Persönliche Seite #5688300
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; }
#5688401
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.
#5688407
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. ;)
Persönliche Seite #5688416
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren