イテレーターや抽象化を使った自前Classの作成

 C++をC言語の経験で使っていると陥る罠は「昔の方法でデータ管理してしまうことです」特にstring型を使わずに低レベルな操作で連結や比較をしてしまう点です。実はC++には標準で文字列を+で連結したり、文字列の比較を現代の言語のように行うことも出来ます。

更にVectorなどのコンテナも充実しています。そう、自前で配列や連結ポインタを管理する必要もありません。更に、ソートや一覧出力は「イテレーター」という標準的な繰り返し処理で可能です。 そう、組み込まれた変数以外であっても、既存のライブラリでソートや一覧が出来てしまう点です。

ただ、完全に自動ではなく、イテレーターやソート、一覧を行うには、自前のClassにそれなりの配慮も必要です。

以下のコードは自前のClassを標準関数によって最大値の取得と一覧の出力を行っています。では、それなりの配慮とは何でしょうか? それは、聞かれることを想定するということです。

最大値を取得するには「比較の手段」を提供する必要があります。そう、「何を持って大きいとするのか」です。人間でも、身長、体重、BMIなど色々な比較を検討する必要があります。

次に一覧を出力する場合、何を出力するかを明示する必要があります。

比較に関しては 演算子 < の振る舞いを指示する必要があります。今回はstring型の比較結果をそのまま返しています。

一覧出力の場合は 演算子 << の振る舞いを指示します。今回はメンバーの中から value を選んで出力しています。たまたま、今回は一つだけですが、複数のメンバーがある場合は「どれを出すのか?」「連結するのか?」をプログラマが指示する必要があります。

なにか面倒ですが、一度苦労して抽象的に処理できる概念を作っておけば、幅広く汎用的に使えるコードが出来上がるので便利になると考えます。


  1. // G++ auto.cpp -std=c++23 -o auto
  2. #include <algorithm>
  3. #include <vector>
  4. #include <string>
  5. #include <iostream>
  6. #include <iterator>
  7. void f(auto &a){
  8.     
  9.    auto it = std::max_element(std::begin(a), std::end(a));
  10.     std::cout << *it << std::endl; // 出力: orange
  11.     
  12. }
  13. class TEST{
  14.     
  15. public:
  16.     std::string value;
  17.      bool operator<(const TEST& other) const {
  18.         return value < other.value;
  19.     };
  20.     
  21.     
  22. };
  23. std::ostream& operator<<(std::ostream& os, TEST& t) {
  24.     os << t.value; // メンバ value を出力
  25.     return os; // ostream を返すことが重要
  26. }
  27. int main() {
  28. // std::vector<std::string> v = {"apple", "banana", "orange"};
  29.     std::vector<TEST> v;
  30.     
  31.     v.push_back(TEST {"apple"});
  32.     v.push_back(TEST {"banana"});
  33.     v.push_back(TEST {"orenge"});
  34.     
  35.     
  36.     f(v);
  37.  
  38. }

イテレーターや抽象化を使った自前Classの作成

 C++をC言語の経験で使っていると陥る罠は「昔の方法でデータ管理してしまうことです」特にstring型を使わずに低レベルな操作で連結や比較をしてしまう点です。実はC++には標準で文字列を+で連結したり、文字列の比較を現代の言語のように行うことも出来ます。 更にVectorなどの...