C++をC言語の経験で使っていると陥る罠は「昔の方法でデータ管理してしまうことです」特にstring型を使わずに低レベルな操作で連結や比較をしてしまう点です。実はC++には標準で文字列を+で連結したり、文字列の比較を現代の言語のように行うことも出来ます。
更にVectorなどのコンテナも充実しています。そう、自前で配列や連結ポインタを管理する必要もありません。更に、ソートや一覧出力は「イテレーター」という標準的な繰り返し処理で可能です。 そう、組み込まれた変数以外であっても、既存のライブラリでソートや一覧が出来てしまう点です。
ただ、完全に自動ではなく、イテレーターやソート、一覧を行うには、自前のClassにそれなりの配慮も必要です。
以下のコードは自前のClassを標準関数によって最大値の取得と一覧の出力を行っています。では、それなりの配慮とは何でしょうか? それは、聞かれることを想定するということです。
最大値を取得するには「比較の手段」を提供する必要があります。そう、「何を持って大きいとするのか」です。人間でも、身長、体重、BMIなど色々な比較を検討する必要があります。
次に一覧を出力する場合、何を出力するかを明示する必要があります。
比較に関しては 演算子 < の振る舞いを指示する必要があります。今回はstring型の比較結果をそのまま返しています。
一覧出力の場合は 演算子 << の振る舞いを指示します。今回はメンバーの中から value を選んで出力しています。たまたま、今回は一つだけですが、複数のメンバーがある場合は「どれを出すのか?」「連結するのか?」をプログラマが指示する必要があります。
なにか面倒ですが、一度苦労して抽象的に処理できる概念を作っておけば、幅広く汎用的に使えるコードが出来上がるので便利になると考えます。
- // G++ auto.cpp -std=c++23 -o auto
- #include <algorithm>
- #include <vector>
- #include <string>
- #include <iostream>
- #include <iterator>
- void f(auto &a){
- auto it = std::max_element(std::begin(a), std::end(a));
- std::cout << *it << std::endl; // 出力: orange
- }
- class TEST{
- public:
- std::string value;
- bool operator<(const TEST& other) const {
- return value < other.value;
- };
- };
- std::ostream& operator<<(std::ostream& os, TEST& t) {
- os << t.value; // メンバ value を出力
- return os; // ostream を返すことが重要
- }
- int main() {
- // std::vector<std::string> v = {"apple", "banana", "orange"};
- std::vector<TEST> v;
- v.push_back(TEST {"apple"});
- v.push_back(TEST {"banana"});
- v.push_back(TEST {"orenge"});
- f(v);
- }