包装STL vector并改变其迭代器的行为

Wrap STL vector and change behavior of its iterator

本文关键字:迭代器 改变 STL vector 包装      更新时间:2023-10-16

有这样的代码:

#include <iostream>
#include <vector>
template <class T>
class A{
public:   
    class iterator : public  std::vector<T>::iterator{
    public:
        T& operator*(){
            ??
        }
    };
    iterator begin(){
        return v.begin(); // error
    }
    iterator end(){
        return v.end(); // error
    }
    void add(const T& elem){
        v.push_back(elem);
    }
private:
    std::vector<T> v;
};
int main() {
    A<int> a;
    a.add(2);
    a.add(4);
    for(A<int>::iterator it = a.begin(); it != a.end(); ++it){
        std::cout << *it << std::endl;
    }
    return 0;
} 

这是std::vector的包装器,带有我自己的附加函数。我想使用std::vector的迭代器,但是我只想改变operator*的迭代器行为:

T& operator*(){
  // do some additional function
  // normal behavior, return value of some element in vector
            ??
}

我如何使用std::vector和它的迭代器只修改operator* ?我还想包装函数像begin()end()迭代器,如何正确包装它们?

编辑:

使用这个主题的答案中的技巧,我设法用以下方法解决了我的问题:

#include <iostream>
#include <vector>
template <class T>
class A {
public:
    class iterator : public std::vector<T>::iterator {
    public:
        iterator(typename std::vector<T>::iterator c) : std::vector<T>::iterator(c) {
        }
        T& operator*() {
            std::cout << "Im overloaded operator*n";
            return std::vector<T>::iterator::operator *();
        }
    };
    iterator begin() {
        return iterator(v.begin());
    }
    iterator end() {
        return iterator(v.end());
    }
    void add(const T& elem) {
        v.push_back(elem);
    }
private:
    std::vector<T> v;
};
int main() {
    A<int> a;
    a.add(2);
    a.add(4);
    for (A<int>::iterator it = a.begin(); it != a.end() ; ++it) {
        std::cout << *it << std::endl;
    }
    return 0;
} 

也许对别人有帮助。

包装stdlib迭代器最好使用迭代器适配器。这项任务远非微不足道,而且还有Boost。简化任务的迭代器库。也许所提供的迭代器之一已经解决了您的问题。

如果你打算自己写这个(我真的不推荐这样做),你应该实现你自己的迭代器,并让它可以从vector::iterator构造,然后重载所有必需的操作符,以满足你的新迭代器模型的概念要求。也从std::iterator继承,以获得性状工作。不要忘记使用一个const变体。本书有一章专门介绍开发自己的迭代器。还要获得标准的副本(c++ 03或c++ 11,在这里无关紧要)。你会需要它的

不幸的是,要做到这一点,唯一的方法是为std::vector及其迭代器类型编写一个完整的包装器。

一个不继承自std::vector<T>::iterator,因为它不需要是一个类。在某些实现中,这只是T*的类型定义,不能从指针继承。也不应该继承标准容器,因为它们缺乏虚析构函数;一种可能是以privateprotected的方式继承,并通过typedefusing使所有的符号和函数可见。最后,您必须重写整个vector及其转发对基实现的调用的迭代器。

我认为这里的答案很可能是不应该改变迭代器的操作符*的行为。操作符重载应该只在非常直观的情况下进行,任何阅读使用操作符的代码的人都会自动知道发生了什么。这方面的一个例子是,如果您有一个矩阵类和重载操作符+。当有人看到你把两个矩阵对象加在一起时,他们很容易知道发生了什么。

但是,当解引用迭代器时,没有直观的感觉会对类产生什么额外的副作用。