std::vector
の連結で演算子が使えない、という話題に対して。
どういう話かというと、こういうことです。
#include <iostream> #include <vector> #include <algorithm> #include <iterator> int main(int, char* []) { std::vector<int> v1; std::vector<int> v2; v1.push_back(10); v1.push_back(20); v1.push_back(30); v2.push_back(100); v2.push_back(200); v2.push_back(300); // v1 += v2; // これをやりたいけど、こうは書けない v1.insert(v1.end(), v2.begin(), v2.end()); // これが一般的な解のひとつ std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; return 0; }
「こんなときはstd::basic_string
を使えばいい」という話を聞きました。
ので、
やってみた。
#include <iostream> #include <algorithm> #include <iterator> #include <string> int main(int, char* []) { std::basic_string<int> s1; std::basic_string<int> s2; s1.push_back(10); s1.push_back(20); s1.push_back(30); s2.push_back(100); s2.push_back(200); s2.push_back(300); s1 += s2; std::copy(s1.begin(), s1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; return 0; }
実行結果。期待どおりのふるまいがえられました。
10 20 30 100 200 300
ぢゃぁ、組み込み型以外だったらどうなるか。ためしてみた。
#include <iostream> #include <algorithm> #include <iterator> #include <string> #include <complex> int main(int, char* []) { std::basic_string<std::complex<double> > s1; std::basic_string<std::complex<double> > s2; s1.push_back(std::complex<double>(10, 10)); s1.push_back(std::complex<double>(20, 20)); s1.push_back(std::complex<double>(30, 30)); s2.push_back(std::complex<double>(100, 100)); s2.push_back(std::complex<double>(200, 200)); s2.push_back(std::complex<double>(300, 300)); s1 += s2; std::copy(s1.begin(), s1.end(), std::ostream_iterator<std::complex<double> >(std::cout, " ")); std::cout << "\n"; return 0; }
実行結果。期待どおりのふるまいがえられました。
(10,10) (20,20) (30,30) (100,100) (200,200) (300,300)
これがOKなら自作の型でも大丈夫だろうと、ためしてみた。
#include <iostream> #include <algorithm> #include <iterator> #include <string> struct Point3D { int x; int y; int z; Point3D(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {} }; std::ostream& operator << (std::ostream& out, const Point3D& point) { return out << "(" << point.x << ", " << point.y << ", " << point.z << ")"; } int main(int, char* []) { std::basic_string<Point3D> s1; std::basic_string<Point3D> s2; s1.push_back(Point3D(1, 2, 3)); s1.push_back(Point3D(4, 5, 6)); s1.push_back(Point3D(7, 8, 9)); s2.push_back(Point3D(10, 20, 30)); s2.push_back(Point3D(40, 50, 60)); s2.push_back(Point3D(70, 80, 90)); s1 += s2; std::copy(s1.begin(), s1.end(), std::ostream_iterator<Point3D>(std::cout, " ")); std::cout << "\n"; return 0; }
実行結果。期待どおりのふるまいがえられました。
(1, 2, 3) (4, 5, 6) (7, 8, 9) (10, 20, 30) (40, 50, 60) (70, 80, 90)
結論。一応std::vector
の代わりをはたせるようです。
要素になる型/クラスにどのようなメンバや演算子やが必要になるかはわかりませんが、仕様の差を承知した上で使うのならば応用がききそうです。
補足。蛇足かもしれませんが、std::basic_string
というのはstd::string
を実現するためのテンプレートです。というか「std::string
はstd::basic_string<char>
の別名」というのが正しい表現かも。
補足2。「文字列クラスだと途中に0があるとそこで切れたりしないの?」という疑問がわいたりしますが、文字列クラスはゼロ終端文字列ではないので大丈夫だそうです。
#include <iostream> #include <algorithm> #include <iterator> #include <string> int main(int, char* []) { std::basic_string<int> s1; s1.push_back(2); s1.push_back(1); s1.push_back(0); s1.push_back(-1); s1.push_back(-2); std::copy(s1.begin(), s1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; return 0; }
実行結果。
2 1 0 -1 -2