包装 STL 向量并更改其迭代器的行为

发布于 2024-12-10 23:00:19 字数 2112 浏览 0 评论 0原文

有这样的代码:

#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::向量及其迭代器仅修改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;
} 

也许这对某人有帮助。

There is such code:

#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;
} 

This is a wrapper for std::vector with my own additional functions. I would like to use std::vector's iterator, however I want only to change behavior of operator* for iterator:

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

How can I use std::vector and its iterator with modification of only operator*? I would like also to wrap functions like begin() and end() for iterator, how to wrap them properly?

EDIT:

Using tips from answers in this topic, I managed to solve my problem in following way:

#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;
} 

Maybe it will be helpful for someone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

影子的影子 2024-12-17 23:00:19

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

如果您要自己编写此代码(我真的不建议这样做),您应该实现自己的迭代器并使其可以从 vector::iterator,然后重载所有必需的运算符以满足新迭代器模型概念的要求。还继承自 std::iterator 以使特征正常工作。不要忘记有一个 const 变体。 本书有一章专门讨论开发您自己的迭代器。还可以获得标准的副本(C++03 或 C++11,在这里并不重要)。你将会需要它。

Wrapping stdlib iterators is done best with iterator adaptors. This task is far from trivial and there is the Boost.Iterator library to simplify the task. Maybe one of the provided iterators already solves your problem.

If you are going to write this on your own (I really don't recommend this), you should implement your own iterator and have it be constructible from a vector::iterator, then overload all required operators to meet the requirements of the concept that your new iterator models. Also inherit from std::iterator to get the traits working. Don't forget to have the a const variant. This book has a chapter devoted to developing your own iterators. Also get a copy of the standard (C++03 or C++11, doesn't matter much here). You are going to need it.

染火枫林 2024-12-17 23:00:19

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

Unfortunately, the only way to do this is to write a complete wrapper for std::vector and its iterator-types. This is a lot of work.

暖树树初阳… 2024-12-17 23:00:19

不需要从 std::vector::iterator 继承,因为它不需要是一类。在某些实现中,这只是 T* 的 typedef,并且不能从指针继承。也不应该继承标准容器,因为它们缺少虚拟析构函数;一种可能性是以privateprotected方式继承,并通过typedefusing.最后,您将不得不重写整个向量及其将调用转发到基本实现的迭代器。

One does not inherit from std::vector<T>::iterator since it does not need to be a class. In some implementations this is just a typedef for T*, and one cannot inherit from a pointer. One also shouldn't inherit from standard containers as they lack a virtual destructor; a possibility is to inherit in a private or protected way and make all symbols and functions visible by means of typedef and using. In the end, you will have to rewrite the entire vector and its iterators that forward calls to the base implementation.

梦开始←不甜 2024-12-17 23:00:19

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

然而,当取消引用迭代器时,对于您的类会产生哪些额外副作用并没有直观的感觉。

I think the answer here is most likely that you shouldn't change the behaviour of operator* for an iterator. Operator overloading should be done only in cases where it is so extremely intuitive that anyone reading the code that uses the operator would automatically know what is happening. An example of this would be if you had a matrix class and overloaded operator+. When someone sees you adding two matrix objects together, they can easily know what is happening.

When dereferencing an iterator however, there is no intuitive sense of what the additional side effects will be for your class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文