今回はテンプレートのお話であるが、実を言うと私も詳しくはなくて間違った理解があるかもしれないのでその点は了承願いたい。
テンプレートはクラスやメソッドに適用されるものであり複数のデータ型に対応したコードを柔軟に記述することが可能となる非常に便利な機能である。通常のクラスの場合は継承を元にした拡張性を目的として使われることが多いと思うがテンプレートの場合は逆に継承は面倒くさいだけで意味はない。
組み込みプラミングにおけるテンプレートの利点は、それが利用されるコード内に直接展開されコンパイルされるということに尽きる。これはクラスという境界を越えてユーザーアプリのコードと一体になって最適化されるということであり、適切に設計さえすれば単独コンパイルしかされない通常のクラスを使った場合に比べてより小さく高速なコードを生成できる可能性がある。だが万能というわけでもない。同じテンプレートを複数利用するケースではコードサイズを逆に大きくしてしまうこともあるので注意は必要である。
Arduinoの場合、メモリ等の制約から継承の意味合いがあまりないとも言えるのでクラスを使うならテンプレート・クラスとして実装したほうが少ない記述量で済むのでお勧めである。テンプレートなんて使ったことがないよという人はクラスも実装できるdefineのようなものと考えるとわかりやすいかもしれない。
具体的な使い方の例は次を参考にどうぞ。
ATtiny85でサーモスイッチを作ってみた。
テンプレート・クラスも良いがテンプート・メソッドもかなり便利。次は、十進変換処理の例(前述のMorseCode.hからの抜粋)であるが実際に利用する整数型のみコンパイルされるため効率は良いし、何より一つのコードで複数の整数型に対応できるというのは便利すぎる。この例では省略されているが対応できない型に対するエラー処理も記述可能だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
template <typename T> void printInt(T value) { if (_index == 0) { uint8_t i = (value < 0); uint8_t j = 0; if (i) { value = -value; _buffer[j++] = '-'; } do _buffer[j++] = (uint8_t)((value % 10) | '0'); while (value /= 10); _count = j--; while (i < j) { uint8_t x = _buffer[i]; _buffer[i++] = _buffer[j]; _buffer[j--] = x; } } } |