假设我的容器类中有以下方法:
Datatype& operator[](const unsigned int Index) // I know this should use size_t instead.
{
return *(BasePointer + Index); // Where BasePointer is the start of the array.
}
我想对MyInstance[Index] = Value
用法实施某种边界检查,以便当用户尝试更改其范围之外的值时,容器会自动调整大小。但是,如果用户试图访问超出容器范围的值,我希望发生其他事情,例如MyVariable = MyInstance[Index]
。如何检测operator[]
的使用方式?
答案 0 :(得分:5)
草图:
返回代理对象而不是实际的数据条目。然后,代理对象定义operator =
来处理赋值情况,并定义隐式转换运算符以用于读出案例。
template <typename T>
class AccessorProxy {
friend class Container<T>;
public:
AccessorProxy(Container<T>& data, unsigned index)
: data(data), index(index) { }
void operator =(T const& new_value) {
// Expand array.
}
operator const T&() const {
// Do bounds check.
return *(data.inner_array + index);
}
private:
AccessorProxy(const AccessorProxy& rhs)
: data(rhs.data), index(rhs.index) {}
AccessorProxy& operator=(const AccessorProxy&);
Container<T>& data;
unsigned index;
};
template <typename T>
class ConstAccessorProxy {
friend class Container<T>;
public:
ConstAccessorProxy(const Container<T>& data, unsigned index)
: data(data), index(index) { }
operator const T&() const {
// Do bounds check.
return *(data.inner_array + index);
}
private:
ConstAccessorProxy(const ConstAccessorProxy& rhs)
: data(rhs.data), index(rhs.index) {}
ConstAccessorProxy& operator=(const ConstAccessorProxy&);
const Container<T>& data;
unsigned index;
};
AccessorProxy<Datatype> operator[](const unsigned int Index)
{
return AccessorProxy<Datatype>(*this, Index);
}
ConstAccessorProxy<Datatype> operator[] const (const unsigned int Index)
{
return ConstAccessorProxy<Datatype>(*this, Index);
}
访问者类可能需要成为容器类的朋友。
找到避免代码重复的方法留给读者练习。 :)
答案 1 :(得分:2)
使用虚拟类类型来表示MyInstance[Index]
之类的表达式,并延迟确定在使用该表达式之前要执行的操作。
class MyContainer {
private:
class IndexExpr {
public:
// Get data from container:
operator const Datatype&() const;
// Expand container if necessary, then store data:
Datatype& operator=(const Datatype& value);
// Treat MyInstance[i] = MyInstance[j]; as expected:
Datatype& operator=(const IndexExpr& rhs)
{ return *this = static_cast<const Datatype&>(rhs); }
private:
IndexExpr(MyContainer& cont, unsigned int ind);
MyContainer& container_;
unsigned int index_;
friend class MyContainer;
};
public:
IndexExpr operator[](unsigned int Index)
{ return IndexExpr(*this, Index); }
// No IndexExpr needed when container is const:
const Datatype& operator[](unsigned int Index) const;
// ...
};
答案 2 :(得分:1)
这不是“如何检测”的完美答案,但是,如果用户通过const实例访问operator[]
,则在索引超出范围时抛出异常。
即。
Datatype const& operator[]() const { .. // don't modify here, throw exception
但是,如果用户通过非const实例访问实例,那么如果索引超出范围(并且在可接受的范围内),则无论如何都要扩展
Datatype& operator[]() { .. // modify here
基本上,您正在使用实例的const属性来确定您的语义是什么(如std::map
中所做的那样 - 即尝试在地图的const实例上调用operator[]
会导致编译器错误 - 即map没有const限定operator[]
,因为如果密钥不存在,则保证函数创建映射。)