Ako použiť šablónu na prehľadné výpisy na sériový port

Zápisník experimentátora

Ak chceme vypísať text na sériový port, používame na to objekt Serial a jeho funkciu print. Ak potrebujeme vypísať viac informácií, programovanie sa mení na nekonečné kopírovanie toho istého príkazu. V zdrojovom kóde sa objaví veľké množstvo skoro rovnakých príkazov, ktoré majú zmenený iba parameter. Dnes si ukážeme, ako toto môžeme elegantne vyriešiť pomocou šablóny.

Príklad

V tomto príklade vidíte dve funkcie, ktoré sa začínajú kľúčovým slovom template. Toto kľúčové slovo hovorí c++ kompilátoru, že sa nejedná o funkciu, ale o šablónu funkcie. To znamená, že kompilátor vygeneruje funkciu podľa šablóny na základe parametra, ktorý dostane. V tomto príklade máme dve šablóny. Prvá je univerzálna, ktorá vygeneruje funkciu pre parameter T. Druhá je špecializovaná len na parameter typu float. V nej vypisujeme premennú typu float na 3 desatinne miesta.

Ďalšie kľúčové slovo, ktoré možno vidíte prvýkrát je operator <<. V c++ môžeme definovať aj správanie špecializovaných operátorov, ktoré sa používajú na vykonanie obvyklej akcie s premennou. V tomto prípade je to operátor <<,  ktorý sa obvykle používa na vykonanie bitového posunu. My ale môžeme operátoru predpísať špecializované správanie, ak budú jeho parametre typu Print a T. Vizuálna podoba operátora nám naznačuje, že by sme ho mohli použiť aj ako vloženie typu T do Print. A presne to funkcia robí. K prvému parametru typu Print zavolá jeho funkciu print a do nej vloží ako parameter typ T. Dôležitý je aj posledný riadok funkcie, ktorou ako výsledok vrátime zase objekt typu Print. To nám umožňuje zreťaziť jednotlivé operátory za sebou.

Výsledok vidíte vo funkcii loop. V jednom riadku som vďaka tomu mohol použiť premennú typu char*, int, String a float.

template<class T> inline Print& operator <<(Print &obj, T arg) {
  obj.print(arg);
  return obj;
}

template<> inline Print& operator <<(Print &obj, float arg) {
  obj.print(arg, 3);
  return obj;
}

int cnt = 0;

void setup() {
  Serial.begin(9600);
  Serial << "Simple Template Print\n";
}

void loop() {
  float rnd = random(100000) / 10000.;
  String original(rnd);
  Serial << "Loop: " << cnt << ", " << rnd << " (" << original << ")\n";
  cnt++;
  delay(2000);
}

Zdrojový kód

Zdrojový kód sa nachádza na serveri GitHub.



Video


12.04.2020


Menu