constexpr return Frage

Hallo,

warum kompiliert test_A aber nicht test_B?
Das ist doch nur die ausführliche Schreibweise von if else.

const byte IODIRA = 0x00;
const byte IODIRB = 0x01;

constexpr byte test_A (const byte pin)
{
  return (pin<8) ? IODIRA : IODIRB;
}

constexpr byte test_B (const byte pin)
{
  if (pin<8)
    return IODIRA;
  else
    return IODIRB;
}


void setup(void) { }

void loop(void) { }

Das ist doch nur die ausführliche Schreibweise von if else.

Nicht ganz.

Du kannst damit auch sowas machen:

const byte var = (pin<8) ? IODIRA : IODIRB;

Das geht mit if/else nicht

Hallo,

aha, dann nehm ich das als gegeben hin. Danke.

Ach ja, und generell darf constexpr in C++11 nur ein einziges return enthalten. Das ist der eigentliche Fehler

Erst mit C++14 ist mehr erlaubt wie if/else, switch/case, und for. Das sollte mit GCC 5 aber eigentlich gehen

Hi

Hatte das Beispiel auf
byte wert;
abgeändert und in dem IF die Variable gesetzt und unterhalb return wert;
Trotz des einen Return kommt der Fehler immer noch - kA warum.

... da ich eh nicht verstehe, Was Da läuft, nehme ich Das Mal so hin.

MfG

Hallo,

eigentlich habe ich den avr-gcc-7.3.0 am laufen. Arduino v1.6.209 ist installiert.
Boardverwaltung: http://downloads.arduino.cc/packages/package_avr_7.3.0_index.json

Ich verwende erstmal die erste constexpr Variante.

@ postmaster:
wolltest du das probieren?

byte x = 0;
const byte var = (x<8) ? IODIRA : IODIRB;

abgeändert und in dem IF die Variable gesetzt und unterhalb return wert;
Trotz des einen Return kommt der Fehler immer noch - kA warum.

C++11 constexpr ist weit, weit limitierter als du denkst. Solche komplexen Anweisungen gehen einfach nicht. Das ist so definiert. Eine Zeile mit return und das wars. Deshalb wird der Konditional-Operator da so oft verwendet

Ich habe mal versucht die IDE Einstellungen auf C++14 zu setzen und das will immer noch nicht. Vielleicht mache ich da aber auch was falsch...

Serenifly:
Ich habe mal versucht die IDE Einstellungen auf C++14 zu setzen und das will immer noch nicht. Vielleicht mache ich da aber auch was falsch...

Hast du das schon mit der Boardverwaltung: http://downloads.arduino.cc/packages/package_avr_7.3.0_index.json
hinzufügen versucht und Version 1.6.209 installiert.

Dann muss man dann die Option in platform.txt unter:
C:\Users\xyz\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.209
ändern.
Mit dem Bsp. klappt es mit der Option C++14 und C++17. Allerdings meckert er die new.cpp an wegen dem Pointer, wenn man die komplette Kompilierungsausgabe aktiviert.

Ich hatte die falsche platform.txt angepasst

Hallo,

meckert er bei dir dann auch die new.cpp an? Ich kann mit der Warnung nichts anfangen.

C:\Users\Doc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.209\cores\arduino\new.cpp:29:6: warning: the program should also define 'void operator delete(void*, unsigned int)' [-Wsized-deallocation]

 void operator delete(void * ptr) {

      ^~~~~~~~

C:\Users\Doc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.209\cores\arduino\new.cpp:33:6: warning: the program should also define 'void operator delete [](void*, unsigned int)' [-Wsized-deallocation]

 void operator delete[](void * ptr) {

meckert er bei dir dann auch die new.cpp an?

Das kann man unterbinden, in dem man es untersagt diese "neuen" Funktionen zu nutzen.
Der Trick: -fno-sized-deallocation

Die beste Unterbringung ist: Eine platform.local.txt neben der platform.txt, welche du schon verändert hast.
Dort einen Eintrag einfügen

compiler.c.elf.extra_flags=-fno-sized-deallocation

Auch kannst du in der Datei deine C++14/C++17 Aktivierung unterbringen.

Zeilen in platform.local.txt überschreiben Zeilen in platform.txt,

Hallo,

klingt gut und hab das verschiedenst probiert. Komplette .txt kopiert, umbenannt und 2 Zeilen geändert.
Dann nur die benötigten 2 Zeilen in die lokale geschrieben.
Also Deine Zeile und die mit gnu++14 und gnu++17 probiert.
Es ändert sich leider nichts. Immer nach dem ersten starten der IDE wird der new pointer angemeckert.
Jede weitere Kompilierung meckert nicht mehr. Alles wie mit gnu++11

Was müßte man überhaupt darunter verstehen "neue Funktionen" werden nicht genutzt?
Von welcher Basis geht man aus?
Ich meine dann braucht man doch zum Bsp. keine gnu++17 Option setzen wenn die IDE nur gnu++14 benutzen soll. Oder so ähnliche Fragen stelle ich mir gerade ... :wink:

Edit:
nicht das wir aneinander vorbeireden, ich bin immer noch im Pfad:
C:\Users\xyz\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.209
unterwegs

\1.6.209\

Habe ich auch im Einsatz.
Allerdings in C++11 Konfiguration, damit ich zum Rest der Welt kompatibel bleibe.

Also Deine Zeile und die mit gnu++14 und gnu++17 probiert.

Da habe ich mich geirrt.
Falsch im Gedächtnis...

Gerade getestet:

Neben der platform.txt eine platform.local.txt angelegt, mit folgendem Inahlt:

compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++17 -fno-sized-deallocation -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto

Das stellt auf C++17 um, und unterbindet die Nutzung der erweitern resize Funktionalität.
(hoffentlich stimmt das jetzt auch)

Was müßte man überhaupt darunter verstehen "neue Funktionen" werden nicht genutzt?
Von welcher Basis geht man aus?

Das neuere C++ wünscht allozierte Speicherbereiche in der Größe verändern zu können.
Die betreffenden Funktionen fehlen in unserem Arduino Core.

Das ist aber nicht schlimm, da wir (bisher) diese Funktionen sowieso nicht brauchen.

Also -fno-sized-deallocation, um dem Compiler zu sagen:
Tue es nicht benutzen. Erwarte noch nicht mal es vorzufinden.

Irgendwelche negativen Begleiterscheinungen sind nicht zu erwarten.
Außer vielleicht Probleme mit der modernen STL.
Aber auch die nutzen wir nicht, weil nicht mitgeliefert.

Hallo,

Besten Dank - funktioniert. :slight_smile:
Und ja, meiner installierten ArduinoSTL bekommt das nicht wenn ich mein vector Bsp. kompilieren möchte.

Und ja, meiner installierten ArduinoSTL bekommt das nicht wenn ich mein vector Bsp. kompilieren möchte.

Du meinst bestimmt:

error: ISO C++1z does not allow dynamic exception specifications

Das ist leider (oder zum Glück) mit C++17 nicht mehr erlaubt.
Mit C++14 gehts noch, haut einem aber schon Warnungen um die Ohren.

Hallo,

richtig. :slight_smile: Dabei nutzt der Testsketch noch gar keine dynamischen Möglichkeiten von vector.

#include <ArduinoSTL.h>  // muss im Lib Manager installiert werden
// #include <algorithm>  // nicht notwendig
using namespace std;

vector<int> v1 {1, 2, 3, 4};
vector<int> v2 {};
vector<int> v3 (19);

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

  Serial.println( v1.size() );
  Serial.println( v2.size() );
  Serial.println( v3.size() );
  Serial.println();
  
  int zahlen[9] = {3, 8, 1, 9, 5, 6, 4, 2, 9};
  sort(zahlen, zahlen + 9);
  for (int i = 0; i < 9; i++) {
    Serial.println(zahlen[i]);
  }

}

void loop() {

}

In file included from C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/memory:20:0,

from C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/char_traits:22,

from C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/iosfwd:21,

from C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/serstream:17,

from C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/ArduinoSTL.h:12,

from C:\Users\xyz\Documents\Arduino\WorkSpace_ATmega2560\eigene_Test-Sketche\vector_Bsp\vector_Bsp.ino:2:

C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/new:40:54: error: ISO C++1z does not allow dynamic exception specifications

_UCXXEXPORT void* operator new(std::size_t numBytes) throw(std::bad_alloc);

^~~~~

C:\Users\xyz\Documents\Arduino\libraries\ArduinoSTL\src/new:46:56: error: ISO C++1z does not allow dynamic exception specifications

_UCXXEXPORT void* operator new[](std::size_t numBytes) throw(std::bad_alloc);

Es ist demnach wieder der new operator beteiligt der eh angemeckert wurde.
Ist aber eigentlich Schade, ich hatte vor irgendwann mit vector die Arrays zu ersetzen.
Da kann man gleich mit size() die Größe ermittelt und muss nicht erst bei Arrays die Anzahl der Elemente berechnen und dabei die Datentypen beachten.

Es ist demnach wieder der new operator beteiligt der eh angemeckert wurde.

Neee...
Den hats hier nur zufällig/absichtlich erwischt.

does not allow dynamic exception specifications
Das Problem ist das werfen der Exception, an der Stelle.
Nur an der Stelle, sonst kein Problem.

Nicht das new, ist das Problem!
Das new ist völlig ok, ansonsten.

Die C++ Entwickler haben durch das Verbot dieses Exception werfens (an der Stelle), ein rekursives Problem unterbunden!

Beispiel:
Du machst im Programm ein new. Es soll Speicher reserviert werden.
Mal angenommen: Dieses Speicher reservieren versagt. Weil nix mehr frei.
Also wirft new eine Exception.
Für die Exception wird Speicher gebraucht.
Also wird new aufgerufen um diesen Speicher zu beschaffen.
Mal angenommen: Dieses Speicher reservieren versagt. Weil nix mehr frei.
Also wirft new eine Exception.
Für die Exception wird Speicher gebraucht.
Also wird new aufgerufen um diesen Speicher zu beschaffen.
usw.

Die Lösung:
Speicher Allokatoren, also new, dürfen keine (dynamischen) Exceptions werfen.
Mit C++11 noch erlaubt
Seit C++14 mit deprecated Warnung versehen
Seit C++17 verboten.

@combie: So wie Du das erklärst, ist das logisch.
Du steckst da echt tief drin. Meine Hochachtung.

Gruß Tommy

Danke für die Blumen...

Ist allerdings nur angelesenes Halbwissen.
Und dann auch noch grob vereinfacht...
Hier habe ich mir vielleicht etwas Vorsprung erarbeiten können, weil ich schon in die Falle getappt bin.

Für uns wichtig:
Natürlich kann man davon ausgehen, dass in der mit C++17 ausgelieferten STL das Problem schon längst behoben ist. Die Korrektur ist nur noch nicht in der ArduinoSTL angekommen, weil wir eigentlich noch auf C++11 Level rum dümpeln.

Hallo,

nach der Erklärung habe ich das Problem auch verstanden. Danke.
Wegen der ArduinoSTL nochmal. Wenn ich bei C++14 oder 17 bleiben möchte mit gcc 7.3 muss ich also warten bis die ArdunioSTL aktualisiert wurde. Mit Option ++11 kompiliert es mit Warnung und lädt hoch, mit ++17 bricht es ab. Schade, darin tummeln sich ja verschiedenste nützliche Zusatzfunktionen. Dann kann ich die STL erstmal deisntallieren. Aber Hauptsache ich kenne erstmal die genauen Zusammenhänge.