Ich hätte das so verstanden, dass dann nur Funktionsparameter erlaubt sind, die schon beim Übersetzen feststehen. Macht natürlich keinen Sinn Ist fragwürdig, dafür einen Funktionsparameter zu verwenden, aber dass es not allowed ist, war mir auch neu.
Ist auch zu unterscheiden zwischen dem Aufrufer der Funktion und dem Funktionsblock selbst:
const sagt dem Aufrufer, dass eine Konstante verwendet werden darf (aber nicht muss)
und der Funktion selbst, dass sie nicht verändert werden darf.
constexpr würde dem Aufrufer sagen, dass eine constexpr verwendet werden muss, und die Funktion selbst könnte beliebig optimiert werden, wie man das bei templates erleben kann. (Nach meinem Verständnis, wenn es denn so vorgesehen wäre)
Es gibt in C und C++ keine echten Konstanten.
Außer die recht modernen constexpr Ausdrücke in C++.
Es ist also nicht gut über Konstanten zu sprechen, oder in Konstanten zu denken, wenn es das nicht gibt.
Das führt nur zu Verwirrungen und logischen Fehlschlüssen, wie man hier im Thread gut sieht.
Beide Sprachen kennen const, was aber nicht Konstant bedeutet, sondern "read only".
Darum ist auch sowas erlaubt: volatile const long irgendwas;
"irgendwas" ist hier für das Programm read only, kann aber jederzeit von Außerhalb geändert werden.
Was einer Konstanten recht ähnlich ist, sind Literale.
z.B. eingestreute magische Zahlen oder #define pi 3.14;
Ich wiederhole:
constexpr Ausdrücke müssen zur Compilezeit ausgewertet werden können.
Funktionsparameter werden zur Laufzeit verarbeitet.
Siehst du den Widerspruch!?!?!
Ich sehe einen Funktionsparameter, von dem der Compiler weiß, dass er schon beim Compilieren feststeht. Wie der Compiler das ausnutzt, würde ich ihm überlassen.
Dass das wie ein Template riecht, nur anders aussieht, stimme ich dir zu.
Unter dem Stichwort const vs. constexpr findet man genug, dein Hinweis, dass const eigentlich readonly bedeutet, ist auch hilfreich.
Ich sehe da keinen Funktionsparameter.
Ich glaube dem Compiler und sehe da ebenfalls eine Unmöglichkeit, ein Paradox.
Einen Widerspruch.
Wie er das ausnutzt?
Er haut es dir/mir/progger um die Ohren.
pinT und pinL sollen hier zur Laufzeit übergeben/besetzt werden.
constexpr Ausdrücke müssen zur Compilezeit ausgewertet werden können.
Schmeckt ihm auch nicht.
Macht auch keinerlei Sinn Parameter zu übergeben, die nicht verändert werden können.
Weil Sinnfrei, haut er einem auch dieses um die Ohren.
Was auch geht, ist die ganze Funktion als constexpr zu definieren wird automatisch erzwungen, dass die Parameter schon zu Compilezeit bekannt sein müssen.
Die Funktion wird zur Compilezeit ausgeführt, wenn die Parameter konstant/Literale sind.
Landet dann nicht im generierten Code.
constexpr int steuerung (int a, int b)
{
return a+b;
}
Was sich die Entwickler dabei gedacht haben?
Da ich nicht an der Entwicklung von C++ beteiligt bin, kann ich solche Dinge nicht felsenfest belegen.
Sehe allerdings die Notwendigkeit, eine Sprache möglichst scharfkantig zu definieren.
Sehe auch die Paradoxie in constexpr Funktionsparametern.
Aus dem Grund halte ich das Verbot für vollkommen OK.
Was wäre wenn Gedankenspiele kann man betreiben, ist Gehirnakrobatik.
Bleibt aber sicherlich ohne Einfluss auf die Realität.
Es sei denn:
Beschwerden/Verbesserungen können an anderer Stelle eingereicht werden.
Bedenke, dieses "was wäre wenn Spielchen" ist irrelevant.
Es ist verboten das zu tun was du willst. Es ist zudem Paradox/Widersprüchlich.
Damit ist der Sack zu.
Ich könnte dir Forth empfehlen.
Da mag sowas gehen, denn:
In Forth wird die Sprache solange modifiziert, bis sie das Problem optimal abbildet.
Forth Programmierer bauen zu dem Behufe häufiger mal ihre eigenen Compiler und Interpreter.
Mehrere Dutzend davon, stecken in so manchem Forth System.
das mit den Schlüsselwörtern ist schon etwas verrückt um das milde auszudrücken. Ich tue mich da auch manchmal schwer. constexpr garantiert eigentlich nur für Variablen die absolute Konstanz zur Compilezeit. Für constexpr Funktionen kann der Compiler immer noch entscheiden ob er diese doch nur zur Laufzeit ausführt. Das ist schon verwirrend.
Wie schon gesagt wurde. Das const sagt dem Compiler hierbei nur das die Variablen innerhalb der Funktion nicht verändert werden. Sie sind ja nur lokal sichtbar. Die Funktion kann dennoch mit unterschiedlichen Übergabewerten aufgerufen werden. Deswegen kann hier kein constexpr verwendet werden, weil die Übergabeparameter mit jedem Funktionsaufruf unterschiedlich sein können, also eben keine Konstanz zur Compilezeit vorhanden ist. Selbst wenn man Konstanten als Parameter übergibt. Die äußeren konstanten Parameter sind ja für die Funktionsaufrufe wiederum unterschiedlich. Man muss unterscheiden zwischen Parameterübergabe und was innerhalb der Funktion passiert.
Mal sacken lassen ...
Das sind alles Feinheiten für gezielte Optimierungen. Ich denke wenn jeder erstmal wenigstens für "konstante" Variablen wirklich const verwenden würde, dann wäre der Programmierwelt auch schon geholfen. const ist schon eine gute Hürde bzw. Hilfe um Tippfehler oder unabsichtliche Änderungen durch den Compiler feststellen zu lassen.
ist natürlich etwas Schade das die IDE soweit hinterher hinkt. Mir fällt es langsam schwer lieb gewonnene Annehmlichkeiten für Forum Beispiele auf "alt" umzuschreiben. Wenn da wenigstens der gcc 9.4 mit kompletten C++17 Standard wäre, dass wäre schon top. Der gcc 9 ist ja nun gut abgehangen vorm nächsten großen Umbruch. Die IDE 2.0 bringt übrigens den gleichen avr-gcc 7.3 mit wie die IDE 1.9.x Verstehe ich nicht ganz. Aber solange es keine 2.x Portable gibt ist die sowieso nichts für mich.
desweiteren habe ich mir gedacht, wenn der TO schon etwas lernen möchte, dann zeige man ihn den nächsten logischen Schritt um von den lokalen statischen Variablen wegzukommen. Das sind hier nur Einmalfunktionen. Ich weiß nicht aus welchen Thread der Sketch stammt und um was es dabei konkret ging. Vielleicht um pauschal enum mit switch case zu zeigen. Ist auch egal.
Deshalb etwas umgebaut. Die Heartbead Funktion habe ich fast so belassen nur eingeschränkt um eine Mehrfachverwendung zu erschweren.
Am Rest kann sich der TO austoben und auf class mit private/public/Methoden usw. umbauen wenn ihm weiterhin Spass macht. Das Bsp. soll unabhängige Taster-Led Objekte Instanzen zeigen. Jedes Objekt hat seinen eigenen Datensatz.