如何在与 C++ 中的派生类型匹配的元素上创建迭代器?

发布于 2024-07-17 00:59:10 字数 618 浏览 3 评论 0原文

我想要一个 C++ 中的迭代器,它只能迭代特定类型的元素。 在下面的示例中,我只想迭代属于 SubType 实例的元素。

vector<Type*> the_vector;
the_vector.push_back(new Type(1));
the_vector.push_back(new SubType(2)); //SubType derives from Type
the_vector.push_back(new Type(3));
the_vector.push_back(new SubType(4)); 

vector<Type*>::iterator the_iterator; //***This line needs to change***

the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
    SubType* item = (SubType*)*the_iterator;
    //only SubType(2) and SubType(4) should be in this loop.
    ++the_iterator;
}

我如何在 C++ 中创建这个迭代器?

I'd like an iterator in C++ that can only iterate over elements of a specific type. In the following example, I want to iterate only on elements that are SubType instances.

vector<Type*> the_vector;
the_vector.push_back(new Type(1));
the_vector.push_back(new SubType(2)); //SubType derives from Type
the_vector.push_back(new Type(3));
the_vector.push_back(new SubType(4)); 

vector<Type*>::iterator the_iterator; //***This line needs to change***

the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
    SubType* item = (SubType*)*the_iterator;
    //only SubType(2) and SubType(4) should be in this loop.
    ++the_iterator;
}

How would I create this iterator in C++?

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

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

发布评论

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

评论(5

一抹淡然 2024-07-24 00:59:10

您必须使用动态强制转换。

the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
    SubType* item = dynamic_cast<SubType*>(*the_iterator);
    if( item != 0 )
       ... 

    //only SubType(2) and SubType(4) should be in this loop.
    ++the_iterator;
}

You must use a dynamic cast.

the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
    SubType* item = dynamic_cast<SubType*>(*the_iterator);
    if( item != 0 )
       ... 

    //only SubType(2) and SubType(4) should be in this loop.
    ++the_iterator;
}
倚栏听风 2024-07-24 00:59:10

没有升压的解决方案。 但是,如果您有权访问 boost 库 - 请按照建议使用 Filter Iterator。

template <typename TCollection, typename T>
class Iterator
{
public:
    typedef typename TCollection::iterator iterator;
    typedef typename TCollection::value_type value_type;

    Iterator(const TCollection& collection,
             iterator it):
        collection_(collection),
        it_(it)
    {
        moveToNextAppropriatePosition(it_);
    }
    bool operator != ( const Iterator& rhs )
    {
        return rhs.it_ != it_;
    }
    Iterator& operator++()
    {
        ++it_;
        moveToNextAppropriatePosition(it_);
        return *this;
    }
    Iterator& operator++(int);
    Iterator& operator--();
    Iterator& operator--(int);
    value_type& operator*()
    {
        return *it_;
    }
    value_type* operator->()
    {
        return &it_;
    }
private:
    const TCollection& collection_;
    iterator it_;
    void moveToNextAppropriatePosition(iterator& it)
    {
        while ( dynamic_cast<T*>(*it) == NULL && it != collection_.end() ) 
            ++it;
    }
};

class A
{
public:
    A(){}
    virtual ~A(){}
    virtual void action()
    {
        std::cout << "A";
    }
};
class B: public A
{
public:
    virtual void action()
    {
        std::cout << "B";
    }
};
int main()
{
    typedef std::vector< A* > Collection;
    Collection c;
    c.push_back( new A );
    c.push_back( new B );
    c.push_back( new A );

    typedef Iterator<Collection, B> CollectionIterator;
    CollectionIterator begin(c, c.begin());
    CollectionIterator end(c, c.end());

    std::for_each( begin, end, std::mem_fun(&A::action) );
}

Solution without boost. But if you have an access to the boost library - use Filter Iterator as was proposed.

template <typename TCollection, typename T>
class Iterator
{
public:
    typedef typename TCollection::iterator iterator;
    typedef typename TCollection::value_type value_type;

    Iterator(const TCollection& collection,
             iterator it):
        collection_(collection),
        it_(it)
    {
        moveToNextAppropriatePosition(it_);
    }
    bool operator != ( const Iterator& rhs )
    {
        return rhs.it_ != it_;
    }
    Iterator& operator++()
    {
        ++it_;
        moveToNextAppropriatePosition(it_);
        return *this;
    }
    Iterator& operator++(int);
    Iterator& operator--();
    Iterator& operator--(int);
    value_type& operator*()
    {
        return *it_;
    }
    value_type* operator->()
    {
        return &it_;
    }
private:
    const TCollection& collection_;
    iterator it_;
    void moveToNextAppropriatePosition(iterator& it)
    {
        while ( dynamic_cast<T*>(*it) == NULL && it != collection_.end() ) 
            ++it;
    }
};

class A
{
public:
    A(){}
    virtual ~A(){}
    virtual void action()
    {
        std::cout << "A";
    }
};
class B: public A
{
public:
    virtual void action()
    {
        std::cout << "B";
    }
};
int main()
{
    typedef std::vector< A* > Collection;
    Collection c;
    c.push_back( new A );
    c.push_back( new B );
    c.push_back( new A );

    typedef Iterator<Collection, B> CollectionIterator;
    CollectionIterator begin(c, c.begin());
    CollectionIterator end(c, c.end());

    std::for_each( begin, end, std::mem_fun(&A::action) );
}
述情 2024-07-24 00:59:10

正如 Paintballbob 在评论中所说,您应该创建自己的迭代器类,也许继承自 vector::iterator。 特别是,您需要实现或覆盖 operator++()operator++(int) 以确保跳过非 SubType 对象(您可以使用 dynamic_castSubType*>() 来检查每个项目)。 在 O'Reilly Net 文章

As paintballbob said in a comment, you should create your own iterator class, perhaps inheriting from vector<Type*>::iterator. In particular, you will need to implement or override operator++() and operator++(int) to ensure that you skip non-SubType objects (you can use dynamic_cast<SubType*>() to check each item). There is a nice overview of implementing your own container and iterator in this O'Reilly Net article.

鯉魚旗 2024-07-24 00:59:10

这是使用 boost 迭代器的另一种方法。 这次,使用 std::remove_copy_if :

std::remove_copy_if(v.begin(), v.end(), 
    boost::make_function_output_iterator(boost::bind(&someFunction, _1)),
    !boost::lambda::ll_dynamic_cast<SubType*>(boost::lambda::_1));

它将调用一个函数(在本例中为 someFunction)。但它可以是 boost::bind 可以构造的任何东西 - 也是一个成员 -函数)对于每个指向 SubType 的指针。

Just another way how to do it using boost iterators. This time, using std::remove_copy_if:

std::remove_copy_if(v.begin(), v.end(), 
    boost::make_function_output_iterator(boost::bind(&someFunction, _1)),
    !boost::lambda::ll_dynamic_cast<SubType*>(boost::lambda::_1));

It will call a function (In this example someFunction. But it can be anything boost::bind can construct - also a member-function) for each pointer that's pointing to a SubType.

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