c++ - 将迭代器实现为具有引用语义的抽象生成器的正确方法

标签 c++ templates pointers iterator generator

我有一个生成值的类,具有如下接口(interface):

template<class T>
class Generator
{
public:
    void advance();
    T* get();
    bool done();
    //...
};

advance 函数使生产者前进,并在内部存储中放置一个指向新值的指针。 get 函数返回此指针,如果 Generator 已完成,则返回 nullptr(尽管 Generator 可以生成 nullptrs 在正常操作过程中,也是如此)。如果 Producer 已完成生成值,则 done 返回 true。 get 返回一个指针,允许客户端与生成的值进行交互,可能会将信息传回给 Generator

这似乎很容易为它实现一个迭代器。 Generator 类不可复制,因此它本身不能是迭代器,因此我创建了一个包含必要操作的简单包装器。我遇到的问题是后增量运算符;推进 Generator 会使旧指针无效。我尝试过不同的想法,但没有一个能让我满足输入迭代器或输出迭代器的所有要求。我不希望我的迭代器拥有该值的拷贝,因为我希望通过指针获得引用语义。我最接近的是让迭代器存储一个增量计数器,并且只在取消引用或比较操作时推进 Generator。这与 const_cast 相得益彰,而且感觉非常危险。有什么方法可以为此接口(interface)实现正确的迭代器吗?

最佳答案

根据你的描述,我认为你能做的最好的就是输入 迭代器。前向迭代器的保证之一是 它们是多 channel 的,我不知道你怎么能用 你的类。你的类(class)不支持背位置, 并从中重新启动,所以一旦一个迭代器前进,就没有了 的其他人可以看到该元素。

当然,您仍然可以使用 输入迭代器,但如果它们还不够,你将不得不 使用迭代器将值复制到 vector 中,然后迭代 在那之上。

编辑:

关于您对 *r++ 工作必要性的评论: 我认为以下内容是合法的:

template <typename T>
class GeneratorIterator
{
    class PostIncrProxy
    {
        GeneratorIterator* myOwner;
    public:
        PostIncrProxy( GeneratorIterator* owner )
            : myOwner( owner )
        {
        }
        ~PostIncrProxy()
        {
            ++(*myOwner);
        }
        T* operator*() const
        {
            return **myOwner;
        }
    };

    Generator<T>* myOwner;
public:
    GeneratorIterator( Generator<T>& owner )
        : myOwner( &owner )
    {
    }
    GeneratorIterator()           //  End iterator...
        : myOwner( nullptr )
    {
    }

    bool operator==( GeneratorIterator const& other ) const
    {
        return (myOwner == nullptr) == (other.myOwner == nullptr);
    }
    bool operator!=( GeneratorIterator const& other ) const
    {
        return !operator==( other );
    }

    T* operator*() const
    {
        assert( myOwner != nullptr );
        return myOwner->get();
    }
    //  -> not necessary if we're iterating over T*.  If 

    GeneratorIterator& operator++()
    {
        assert( myOwner != nullptr );
        myOwner->advance();
        if ( myOwner->done() ) {
            myOwner = nullptr;
        }
    }

    PostIncrProxy operator++(int)
    {
        return PostIncrProxy( this );
    }
};

这会将实际递增推迟到 完整的表达,我想这在某些方面可能是个问题 退化的案例,但我至少会尝试一下。 (如果更糟 最坏的情况是,您还可以在 PostIncrProxy::operator*,一旦你恢复了返回 值,然后将其myOwner设置为null,测试用例 在析构函数中。)

关于c++ - 将迭代器实现为具有引用语义的抽象生成器的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21413422/

相关文章:

c++ - 只读取文本文件中的给定行?

database - 在模板中使用 Django 链 如何?

c++ - 使用T的默认构造函数作为默认初始值

python - Django 通过信号使模板缓存失效

c - 如何在 C 中检查 char 数组的前两个字符?

c++ - 隐式转换 : const reference vs non-const reference vs non-reference

c++ - 队列元素的打印队列

c++ - 是否可以使用现有的 Makefile 在 Code::Blocks 中构建项目?

c - 插入和操作结构体指针的动态数组

c# - C++ 到 C# 的包装 - 如何处理 C# 中的双指针数组