Gibt es eine Möglichkeit bei range based zu bleiben?
Die untere Methode writePortBurst bekommt der User zu sehen.
Hier soll ein Array mit byte Werten übergeben werden.
Diese Werte prüfe/filter ich mit einer Maske.
Deswegen müssen diese Werte in einen Zwischenspeicher localArray.
Dieses localArray wird dann letztlich an writeBurst übergeben welches die Werte hintereinander auf den Bus schickt.
Jetzt die Frage, gibt es eine Möglichkeit in der range based in writePortBurst die einzelnen geprüften Elemente in das localArray ohne Index [i] zu schreiben? Ansonsten müßte ich auf range based verzichten.
// private
uint8_t myPCA9538::writeBurst(const uint8_t reg, auto &arr)
{
line.beginTransmission(addr);
line.write(reg);
for (auto a : arr) {
line.write(a);
}
const uint8_t error = line.endTransmission();
return error;
}
// public
uint8_t myPCA9538::writePortBurst (auto &arr)
{
uint8_t localArray [sizeof(arr)] = {0};
for (auto a : arr) {
const uint8_t filteredMask = ioMask & a; // I/O direction validity filter
localArray[i] = filteredMask; // <<< ?
}
const uint8_t error = writeBurst(ctrlReg.out, localArray);
return error; // possible line failure, 0=OK
}
vector und push_back: Ich möchte keine Elemente hinzufügen o.ä.
Edit: ginge ja, aber ohne STL erstmal nicht
Es muss keine bereichsbasierte For Schleife sein. Es wäre nur schön wenn man das nutzen könnte, erzeugt weniger Fehler.
Ich überlege mir das nochmal in Ruhe. Aktuell könnte ich es nach außen vereinfachen und intern bleibts altmodisch. Übrigens, STL gibts dafür erstmal nicht.
wenn man weiß was man tut kann nichts passieren. Sagen vorher immer alle.
Wenn es innerhalb der Schleife bleiben soll, dann vielleicht mit Adressenberechnung. Link
Ob das eleganter wie i++ ist weiß ich nicht. Auf jeden Fall vermutlich langsamer.
Vermutlich gehe ich zurück auf altmodisch. Man muss immer die passende Lösung zum Problem verwenden. Nicht das passende Problem zur Lösung suchen ...
Wenn range based nicht passt, dann passt range based nicht.
funktioniert, hatte ich aber nicht vollständig getestet. Anzahlberechnung ist korrigiert. Beim testen fiel noch auf das die erste range based loop zwingend eine Referenz benötigt. Nimmt man den Adressoperator weg bleibt localArray leer.
Stream &cout {Serial};
#include <Streaming.h>
byte data [] = {31, 33, 36, 40, 45, 54, 70, 170};
void setup()
{
Serial.begin(250000);
cout.println(F("\nuC Reset ### ###"));
rangeBased(cout, data);
}
void loop (void)
{ }
void rangeBased (Stream &out, auto &arr)
{
uint8_t localArray [sizeof(arr)/sizeof(arr[0])] = {0};
out.println("\nlocalArray <- arr");
for (auto &a : arr)
{
size_t index = &a - &arr[0];
localArray[index] = a;
}
out.println("\narr:");
for (auto a : arr)
{
out << "value " << a << endl;
}
out << "Anzahl Elemente " << sizeof(arr)/sizeof(arr[0]) << endl;
out.println("\nlocalArray:");
for (auto a : localArray)
{
out << "value " << a << endl;
}
out << "Anzahl Elemente " << sizeof(localArray)/sizeof(localArray[0]) << endl;
}
vielleicht kann mir jemand auf die Sprünge helfen.
Ein Array kann man wie in #8 gezeigt übergeben und weiterverarbeiten.
Das Gleiche kann ich in einer Header only Lib machen.
Schreibe ich jedoch eine Lib mit .h und .cpp bekomme ich eine undefinierte Referenz Meldung.
im Header public
uint8_t togglePinBurst (auto &arr);
in cpp
uint8_t togglePinBurst(auto &arr)
{
line.beginTransmission(addr); // connect
line.write(ctrlReg.out);
for (auto &a : arr) {
line.write(a); // und senden
}
const uint8_t error = line.endTransmission(); // disconnect
return error; // possible line failure, 0=OK
}
c:/avrtoolchain/avr-gcc-11.3.0_mingw32_binutils2.38/bin/../lib/gcc/avr/11.3.0/../../../../avr/bin/ld.exe: C:\Users\Worker\AppData\Local\Temp\ccB3bvXx.ltrans0.ltrans.o: in function `.Loc.1173':
<artificial>:(.text.startup+0x292): undefined reference to `unsigned char myPCA9538::togglePinBurst<unsigned char [16]>(unsigned char (&) [16])'
collect2.exe: error: ld returned 1 exit status
Ich könnte schwören, auto schon im CPP benutzt zu haben, allerdings nicht in einer Funktionssignatur. Wohl aber mit STL-Containern - mag sein, dass da die nötigen Templates generiert werden.
Das kann gut sein!
Ist ja auch kein Problem, wenn der Datentype zur Kompilezeit bekannt ist.
Ist er aber hier nicht! (also bei mir schon, bei Doc_Arduino nicht)
vielen Dank. Na wenn das Templates werden muss ich mich nicht wundern wenn es nur Header only funktioniert. Bekommt man das auch ohne auto hin. Stehe auf dem Schlauch. Mit Zeiger und Adressoperator irgendwie bekomme ich das nicht hin. Geht das überhaupt ohne auto?
Das zu übergebende Array ist ein byte Array.
Wenn das nicht geht kann ich for range based in der Funktion nicht nutzen. Dann muss das klassisch geschrieben werden. Oder die Lib wird Header only.
Das ist der richtige Weg! (?)
(sofern nichts dagegen spricht)
Und wenn du ein inline davor setzt, gibts im fertigen Code auch keine Duplikate oder Errors.
Ob mit oder ohne Auto, oder Templates....
Wenn der Datentype in der Übersetzungseinheit bekannt ist, ist alles gut.
wie man das ohne auto für nicht Header only Lib schreibt weiß ich im Moment nicht, falls möglich. Ich werde es Header only umbauen, ist nur eine kleine Lib für einen I2C Port Expander. Vielleicht wird später auch ein echtes Klassen-Template daraus. Mal sehen. Ist eine Spielwiese. Abgesehen vom for range based muss man weniger Parameter übergeben. Deswegen möchte ich es in der Form gern beibehalten. Innerhalb der Lib wäre mir das egal gewesen. Nur im Hauptprogramm immer die Größe des Arrays als 2. Parameter mitgeben wird irgendwann lästig.
Ich danke euch, hätte mir sonst noch ewig einen Kopf gemacht.
Die Ansage, Prototypen in die *.h und Code in die *.cpp, ist nicht mehr Zeitgemäß. (von wenigen einsamen Notlagen mal abgesehen)
War damals (in *.c) nötig, hat aber im laufe der Zeit seinen Sinn verloren.
So wie auch inline in der gleichen Zeit seine Bedeutung geändert hat.
Das ist beides eine Einheit, eine Idee, ein einziger Zusammenhang.
Da habe ich keine Ahnung, sehe keine Chance.
Wie gesagt...
Wenn du der Übersetzungseinheit nicht den Datentype bereitstellen kannst... nope.
Korrektur/Nachtrag:
Eine Chance mag es geben, Iteratoren statt der Arrays übergeben!
ich konnte mich bis jetzt noch nicht entscheiden ob ich nur noch Header only schreibe. Aber gut, hast recht. Dann soll es so sein. Danke für den Hinweis.
Dabei fällt mir ein, dass irgendwann noch die Modulprogrammierung kommt, dann wird das mit den Libs sowieso anders. Hat es damals nur nicht mehr in den C++20 Standard geschafft. Soll irgendwann reinkommen. Dann schreibt man Module statt Bibliotheken. Auch das inkludieren soll damit einfacher werden. Falls das noch nicht bekannt war.