为稀疏向量重载operator []

时间:2009-09-06 16:37:29

标签: c++ operator-overloading subscript sparse-matrix

我正在尝试用C ++创建一个“稀疏”矢量类,如下所示:

template<typename V, V Default>
class SparseVector {
    ...
}

在内部,它将由std::map<int, V>表示(其中V是存储的值的类型)。如果地图中没有元素,我们将假装它等于模板参数中的值Default

但是,我在重载下标运算符[]时遇到问题。我必须重载[]运算符,因为我将此类中的对象传递给期望[]正常工作的Boost函数。

const版本很简单:检查索引是否在地图中,如果是,则返回其值,否则返回Default

但是,非const版本要求我返回一个引用,这就是我遇到麻烦的地方。如果该值仅为 read ,我不需要(也不想)向地图添加任何内容;但是如果它是写的,我可能需要在地图中添加一个新条目。问题是重载的[]不知道值是还是。它只返回一个参考。

有什么方法可以解决这个问题吗?或者也许可以解决它?

3 个答案:

答案 0 :(得分:13)

可能有一些非常简单的技巧,但我认为operator[]只需返回可以从V(并转换为V)分配的东西,不一定是V&amp ;.所以我认为你需要返回一个带有重载operator=(const V&)的对象,它会在你的稀疏容器中创建这个条目。

但是,您必须检查Boost函数对其模板参数的作用 - 用户定义的V转换会影响转换链的可能性,例如,防止在同一个链中有任何更多用户定义的转换

答案 1 :(得分:9)

不要让非const运算符&amp;实现返回一个引用,但是一个代理对象。然后,您可以实现代理对象的赋值运算符,以区分对operator []的读访问和写访问。

这里有一些代码草图来说明这个想法。这种方法并不漂亮,但很好 - 这就是C ++。 C ++程序员不会浪费时间参加选美比赛(他们也不会有机会)。 ; - )

template <typename V, V Default>
ProxyObject SparseVector::operator[]( int i ) {
   // At this point, we don't know whether operator[] was called, so we return
   // a proxy object and defer the decision until later
   return ProxyObject<V, Default>( this, i );
}

template <typename V, V Default>
class ProxyObject {
    ProxyObject( SparseVector<V, Default> *v, int idx );
    ProxyObject<V, Default> &operator=( const V &v ) {
      // If we get here, we know that operator[] was called to perform a write access,
      // so we can insert an item in the vector if needed
    }

    operator V() {
      // If we get here, we know that operator[] was called to perform a read access,
      // so we can simply return the existing object
    }
};

答案 2 :(得分:1)

我想知道这种设计是否合理。

如果要返回引用,则表示该类的客户端可以将operator[]的结果存储在引用中,并在以后读取/写入它。如果您没有返回引用,和/或每次处理特定索引时都不插入元素,他们怎么能这样做? (另外,我觉得标准需要一个正确的STL容器,让operator[]让操作符返回一个引用,但我不确定。)

您可以通过为您的代理提供operator V&()(这将创建条目并分配默认值)来规避这一点,但我不确定这不会只是打开另一个循环漏洞有些情况我还没有想到。

std::map通过指定该运算符的非const版本始终插入元素(并且根本不提供const版本)来解决此问题。

当然,您总是可以说不是现成的STL容器,operator[]不会返回用户可以存储的普通引用。也许那没关系。我只是好奇。