Jak použít šablonu na přehledné výpisy na sériový port

Zápisník experimentátora

Pokud chceme vypsat text na sériový port, používáme na to objekt Serial a jeho funkci print. Pokud potřebujeme vypsat více informací, programování se mění na nekonečné kopírování téhož příkazu. Ve zdrojovém kódu se objeví velké množství skoro stejných příkazů, které mají změněný pouze parametr. Dnes si ukážeme, jak toto můžeme elegantně vyřešit pomocí šablony.

Příklad

V tomto příkladu vidíte dvě funkce, které se začínají klíčovým slovem template. Toto klíčové slovo říká c++ kompilátoru, že se nejedná o funkci, ale o šablonu funkce. To znamená, že kompilátor vygeneruje funkci podle šablony na základě parametru, který dostane. V tomto příkladu máme dvě šablony. První je univerzální, která vygeneruje funkci pro parametr T. Druhá je specializovaná pouze na parametr typu float. V ní vypisujeme proměnnou typu float na 3 desetinná místa.

Další klíčové slovo, které pravděpodobně vidíte poprvé je operator <<. V c++ můžeme definovat i chování specializovaných operátorů, které se používají k provedení obvyklé akce s proměnnou. V tomto případě je to operátor <<, který se obvykle používá k provedení bitového posunu. My ale můžeme operátoru předepsat specializované chování, pokud budou jeho parametry typu Print a T. Vizuální podoba operátora nám naznačuje, že bychom ho mohli použít i jako vložení typu T do Print. A přesně to funkce dělá. K prvnímu parametru typu Print zavolá jeho funkci print a do ní vloží jako parametr typ T. Důležitý je i poslední řádek funkce, kterou jako výsledek vrátíme zase objekt typu Print. To nám umožňuje zřetězit jednotlivé operátory za sebou.

Výsledek vidíte ve funkci loop. V jednom řádku jsem díky tomu mohl použít proměnnou 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 se nachází na serveru GitHub.



Video


12.04.2020


Menu