これをサポートするにsubstr()
は、元の文字列のどの部分が参照されているかを追跡するプロキシオブジェクトを返すようにを作成する必要があります。プロキシオブジェクトはオーバーロードoperator=
し、その中で参照先のサブストリングを新しく割り当てられたサブストリングに置き換えます。
コメントに応じて編集する:プロキシの考え方は、プロキシを返すことはまだ閉じた操作であるというプロキシのクラスに十分に似ているということです。つまり、ユーザーの観点からは、表示されるのは元のタイプのオブジェクトだけです。 、ただし、プロキシなしでは不可能な(または実装がはるかに難しい)機能があります。この場合、プロキシクラスは文字列クラスに対してプライベートであるため、ユーザーは一時的なものを除いてプロキシクラスのインスタンスを作成することはできません。その一時的なものを割り当てると、その親文字列を変更するために使用できます。他の方法でプロキシを使用すると、文字列が生成されます。
これにより、元の文字列内ですべてを実行しようとするよりも多くのメリットがあります。各プロキシオブジェクトは一時オブジェクトです。コンパイラは、必要に応じて一時オブジェクトを作成する方法を追跡し、最後に適切に破棄します。完全な式など。コンパイラは、特定の割り当てが参照するサブ文字列を追跡し、その値を使用しようとすると自動的に文字列に変換します。簡単に言えば、コンパイラーは、関連するほとんどすべてのハードワークを処理します。
これがいくつかの実用的なコードです。周囲の文字列クラスは非常に最小限です(たとえば、検索機能がありません)。文字列クラスの便利なバージョンにかなりの量を追加することを期待しています。ただし、プロキシクラスは完全です。機能が完全なバージョンの文字列クラスでは、プロキシクラスが(あったとしても)大きく変わることはないと思います。
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
class string {
std::vector<char> data;
public:
string(char const *init) {
data.clear();
data.assign(init, init+strlen(init));
}
string(string const &s, size_t pos, size_t len) {
data.assign(s.data.begin()+pos, s.data.begin()+pos+len);
}
friend class proxy;
class proxy {
string &parent;
size_t pos;
size_t length;
public:
proxy(string &s, size_t start, size_t len) : parent(s), pos(start), length(len) {}
operator string() { return string(parent, pos, length); }
proxy &operator=(string const &val) {
parent.data.erase(parent.data.begin()+pos, parent.data.begin()+pos+length);
parent.data.insert(parent.data.begin()+pos, val.data.begin(), val.data.end());
return *this;
}
};
proxy substr(size_t start, size_t len) {
return proxy(*this, start, len);
}
friend std::ostream &operator<<(std::ostream &os, string const &s) {
std::copy(s.data.begin(), s.data.end(), std::ostream_iterator<char>(os));
return os;
}
};
#ifdef TEST
int main() {
string x("Hello");
std::cout << x << std::endl;
std::cout << x.substr(2, 3) << std::endl;
x.substr(2, 3) = "DD";
std::cout << x << std::endl;
return 0;
}
#endif
編集2:部分文字列の部分文字列に関する限り、それは異なります。現在カバーされていない1つの状況は、サブストリングのサブストリングに割り当てて、元のストリングに影響を与える場合です。このようなものが必要な場合は、x=y.substr(1,4).substr(1,2);
そのままで問題なく動作します。最初のプロキシは文字列に変換され、2番目のsubstrはその文字列で呼び出されます。
必要な場合:x.substr(1,4).substr(1,2) = "whatever"
; 現在は機能しません。それが多くを達成するかどうかはわかりませんが、それが達成されると仮定すると、それをサポートするための追加はかなり最小限です-プロキシにsubstrメンバーを追加します:
proxy substr(size_t start, size_t len) {
return proxy(parent, pos+start, len);
}