的解决方案是使用“代理”对象,将延迟实际操作:
#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
因为您可能需要从非常量实例中读取,所以无法使用该属性,这就是您必须延迟操作的原因:分配发生在“访问和编译器之后”之后告诉你访问是否将被用作分配目标。
因此,这个想法是,在访问时,您只需存储已请求的索引,并等待知道是正在进行读取还是写入操作。通过提供从代理到T
的隐式转换运算符,您知道何时发生读取操作,通过向T
中的代理提供并分配运算符,您知道何时发生写入操作。
您可能想要查找*代理对象*,这通常用于区分读取和写入。 – templatetypedef
请参见Scott Meyers [更有效的C++]中的第30项“代理类”(http://www.amazon.com/More-Effective-Improve-Programs-ebook/dp/B004VSMDNY/ref=la_B004BBEYYW_1_2?s=books&ie= UTF8&qid = 1381129998&sr = 1-2)进行广泛的讨论,包括代理类可以为您提供的令人惊讶的缺陷(与用户定义的转换有关)。该材料是[强制性阅读](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。 – TemplateRex