解決策は、実際の操作を遅らせる「プロキシ」オブジェクトを使用することです。
#include <vector>
#include <iostream>
template<typename T>
struct MyArray {
std::vector<T> data;
MyArray(int size) : data(size) {}
struct Deref {
MyArray& a;
int index;
Deref(MyArray& a, int index) : a(a), index(index) {}
operator T() {
std::cout << "reading\n"; return a.data[index];
}
T& operator=(const T& other) {
std::cout << "writing\n"; return a.data[index] = other;
}
};
Deref operator[](int index) {
return Deref(*this, index);
}
};
int main(int argc, const char *argv[]) {
MyArray<int> foo(3);
foo[1] = 42;
std::cout << "Value is " << foo[1] << "\n";
return 0;
}
非 const インスタンスから読み取る必要がある可能性があるため、単純const
性は使用できません。これが、操作を遅らせる必要がある理由です。割り当てはアクセスの「後」に行われ、アクセスがアクセスされたかどうかコンパイラーは通知しません。後で割り当てのターゲットとして使用されるかどうか。
したがって、アクセス時に、要求されたインデックスを保存し、読み取りまたは書き込み操作が行われているかどうかを確認するのを待つという考え方です。プロキシから暗黙的な変換演算子を提供することT
で、読み取り操作がいつ発生するかを知ることができます。代入演算子をプロキシに提供することでT
、書き込みがいつ発生するかを知ることができます。