Abkürzung für else ?

Hallo, ich habe einen Beispiel-Code übernommen und wundere mich über manche schreibweisen, die scheinbar undokumentert sind, oder ich zu Blöd es zu finden.

Ich vermute anhand des Codes das dieses hier für ein "else" steht:

} (( {

Die vermutung weil es mitten in tausend "if"- verschachtelungen steht.
Kann das jemand bestätigen ?

C++ ist sehr gut dokumentiert!
Alles!
Sogar die undefinierten Dinge/Verhalten sind dokumentiert.

Eine lustige Fantasie, du hast.

Benutze mal Strg-T in der IDE zum formatieren.

Solche if Monster sind fast immer deutlich zu vereinfachen mit switch case und dem beachten des EVA Prinzipes.

Was heisst das denn ? ich finde leider nichts dazu. Die erste geschweifte Klammer beendet doch logischerweise eine if, was die zwei öffnenden Klammern dann tun ist mir schleierhaft, aber danach öffnet ja wieder eine geschweifte Klammer.
Also irgendwas passiert doch da, kann nur eine "else" sein, macht doch sonst keinen Sinn.
Wenn es so gut dokumentiert ist, muss das ja irgenwo zu fnden sein.

und hier habe ich das nochmal gefunden, im offiziellen Beispiel zu Bluetooth-Discover:

#include <map>
#include <BluetoothSerial.h>

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif

BluetoothSerial SerialBT;

#define BT_DISCOVER_TIME 10000
esp_spp_sec_t sec_mask = ESP_SPP_SEC_NONE;  // or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE to request pincode confirmation
esp_spp_role_t role = ESP_SPP_ROLE_SLAVE;   // or ESP_SPP_ROLE_MASTER

// std::map<BTAddress, BTAdvertisedDeviceSet> btDeviceList;

void setup() {
  Serial.begin(115200);
  if (!SerialBT.begin("ESP32test", true)) {
    Serial.println("========== serialBT failed!");
    abort();
  }
  // SerialBT.setPin("1234"); // doesn't seem to change anything
  // SerialBT.enableSSP(); // doesn't seem to change anything

  Serial.println("Starting discoverAsync...");
  BTScanResults *btDeviceList = SerialBT.getScanResults();  // maybe accessing from different threads!
  if (SerialBT.discoverAsync([](BTAdvertisedDevice *pDevice) {
        // BTAdvertisedDeviceSet*set = reinterpret_cast<BTAdvertisedDeviceSet*>(pDevice);
        // btDeviceList[pDevice->getAddress()] = * set;
        Serial.printf(">>>>>>>>>>>Found a new device asynchronously: %s\n", pDevice->toString().c_str());
      })) {
    delay(BT_DISCOVER_TIME);
    Serial.print("Stopping discoverAsync... ");
    SerialBT.discoverAsyncStop();
    Serial.println("discoverAsync stopped");
    delay(5000);
    if (btDeviceList->getCount() > 0) {
      BTAddress addr;
      int channel = 0;
      Serial.println("Found devices:");
      for (int i = 0; i < btDeviceList->getCount(); i++) {
        BTAdvertisedDevice *device = btDeviceList->getDevice(i);
        Serial.printf(" ----- %s  %s %d\n", device->getAddress().toString().c_str(), device->getName().c_str(), device->getRSSI());
        std::map<int, std::string> channels = SerialBT.getChannels(device->getAddress());
        Serial.printf("scanned for services, found %d\n", channels.size());
        for (auto const &entry : channels) {
          Serial.printf("     channel %d (%s)\n", entry.first, entry.second.c_str());
        }
        if (channels.size() > 0) {
          addr = device->getAddress();
          channel = channels.begin()->first;
        }
      }
      if (addr) {
        Serial.printf("connecting to %s - %d\n", addr.toString().c_str(), channel);
        SerialBT.connect(addr, channel, sec_mask, role);
      }
    } else {
      Serial.println("Didn't find any devices");
    }
  } else {
    Serial.println("Error on discoverAsync f.e. not working after a \"connect\"");
  }
}


Klammern klammern Dinge ein.
Das heißt das.
Was sie einklammern, hast du ja weggeschnitten.

Wenn man eine Annahme macht die nur auf Fantasie beruht, nicht auf Realität, dann wird man keine Doku dazu finden.

Ein Editor zeigt dir das an:
image

Da wird eine Lambda Funktion in einer if Bedingung definiert.
Vielleicht nicht hübsch, aber durchaus ok und hat auch nix mit else zu tun

Eventuell helfen ein paar Einrückungen:

  if (SerialBT.discoverAsync
       ([](BTAdvertisedDevice * pDevice) 
         {
           // BTAdvertisedDeviceSet*set = reinterpret_cast<BTAdvertisedDeviceSet*>(pDevice);
           // btDeviceList[pDevice->getAddress()] = * set;
           Serial.printf(">>>>>>>>>>>Found a new device asynchronously: %s\n", pDevice->toString().c_str());
         }
       )
     )
  {
      delay(BT_DISCOVER_TIME);
    // ...
  } 
  else 
  {
    Serial.println("Error on discoverAsync f.e. not working after a \"connect\"");
  }

Nutze ich gerne, macht es aber bei diesem Beispiel für mich nicht deutlicher. Konntest Du bei #3 aber noch nicht wissen :wink:

Man kann immer mehrere Funktionen und anweisungenin einem Block mit {} gruppieren.

 })) {

In diesem Fall ist die zweite runden Klammer die schließende Klammer des IF.
Die schließende geschweifte Klammer ist ein Teil der "Bedingung" des IF.
Die öffnende geschweifte Klammer ist der Block für den das IF gilt.

Grüße Uwe

Ein Unterschied ist mir dann doch noch aufgefallen:

Ist vielleicht marginal, aber eben doch nicht das gleiche.

Die runden Klammern kann man abzählen. Und haben nichts mit else zu tun.
Was du nicht kennst, ist die Definition einer lambda-Funktion hier:

Ich finde das [] auch nicht intuitiv verständlich, aber dokumentiert ist es.

Spannender wird es, wenn da was drin steht.

wikipedia ist auch nicht immer das beste wenn es ums Erklären geht.

Eine Lambda-Funktion in C++ ist wie eine kurze Notiz, die du direkt dort schreibst, wo du sie brauchst – statt einen ganzen Brief (eine "normale" Funktion) zu verfassen. Sie hat keinen Namen, kann aber Eingaben entgegennehmen und Ergebnisse liefern. Man nutzt sie oft für einfache, einmalige Aufgaben, z. B. um eine Aktion kurz in einer Schleife oder einer anderen Funktion zu definieren.

Einfaches Code-Beispiel:

Stell dir vor, du möchtest eine Mini-Funktion schreiben, die zwei Zahlen addiert. Mit einer Lambda-Funktion geht das so:

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

  // Lambda-Funktion direkt aufrufen und Ergebnis ausgeben
  Serial.print("Ergebnis: ");
  Serial.println(   [] (int a, int b) // Definition der Parameter der Lambda-function
                    { return a + b; } // Code der lambda-function
                       (3, 5) // sofortiger Aufruf mit den Zahlen "3" und "5"
                 ); // schließende runde Klammer von Serial.println
}

void loop() {
}

Und da es ja um kompakte Schreibweise geht wird alles direkt hintereinander geschrieben.
Das ist dann schön kompakt aber für jemanden der es gerade erst lernt schwerer zu verstehen.

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

  // Lambda-Funktion direkt aufrufen und Ergebnis ausgeben
  Serial.print("Ergebnis: ");
  Serial.println( [](int a, int b) { return a + b; }(3, 5) ); // Ausgabe: 8
}

void loop() {
}

So würde das ganze mit einer normalen function aussehen

// Normale Funktion "add" definieren
int add(int a, int b) {
  return a + b;
}

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

  // Funktion aufrufen und Ergebnis ausgeben
  int ergebnis = add(3, 5);
  Serial.print("Ergebnis: ");
  Serial.println(ergebnis); // Ausgabe: 8
}

void loop() {
}

Vielleicht noch als Ergänzung: Lambdas werden häufig als Callbackfunktionen genutzt, und direkt an der Stelle geschrieben, wo "normalerweise" der Name einer Callbackfunktion übergeben würde, die irgendwo anders definiert wurde. Üblicherweise interessiert der Name ohnehin niemanden, weil die Funktion für nichts anderes benutzt wird und mit einem Lambda ist die Funktion genau da zu finden, wo sie benutzt wird.

Lambda Funktionen spielen ihre Fähigkeiten voll aus, wenn die Capture Klausel (Aufnahmeklausel) genutzt wird.

Ein ähnliches Verhalten wäre nur über das friend Statement möglich, ist aber viel weniger selektiv.

na Combie schon wieder keine Lust zu erklären was die Capture-Klausel ist?

Nein.
Die Variable ergebnis ist in der Ausgangsfunktion nicht enthalten und überflüssig.

Achja. Kritisieren aber nicht schreiben wie es dann aussehen würde.
Wenn es denn gepostet worden wäre. Kenner der Materie würden einen Blick drauf werfen und wissen jo passt. Anfänger würden etwas daraus lernen und mehr verstehen wenn es explizit gepostet worden wäre.

Nee.,,

  1. Stecke den Kopf in dein C++ Buch, denn: Selber lesen macht selber schlau!
  2. Bitte, lasse die Seitenhiebe.