可以定义一个C ++变量来接受任何BidirectionalIterator吗?

时间:2013-02-18 04:37:58

标签: c++ stl iterator

无论是否通过良好的设计,我的main()方法都声明了一个变量,它需要期望任何满足BidirectionalIterator定义的迭代器(特别是list<>::iteratorvector::iterator)在使用什么数据结构(由输入参数确定)。由于我无法模板main()方法,如何实现这一目标?

例如,而不是:

int main(int argc, const char* argv[]) {
    vector<Person>::iterator iterator0;
    list<Person>::iterator iterator1);
    multimap<string, Person>::iterator iterator2;
}

由于所有迭代器都满足BidirectionalIterator的要求,我想这样做:

int main(int argc, const char* argv[]) {
    bidirectionaliterator iterator0;
}

然后,我不必不断检查程序使用if-statements来存储迭代器和使用我想要的迭代器的数据结构类型。

2 个答案:

答案 0 :(得分:1)

听起来你想要typedef:

typedef std::vector<Person> person_container;
typedef person_container::iterator mybidirectionaliterator;

然后,只要您想要更改基础容器,您所要做的就是将std::vector<Person>更改为其他内容。虽然,您仍然无法在此处分配任何迭代器,但您必须使用兼容的迭代器。但是,您熟悉C ++ 11中的auto关键字吗?很多时候你不再需要写出迭代器,即auto myiter = some_container.begin();就足够了。

此外,为了获得更好的答案,有助于展示您如何使用迭代器而不仅仅是声明它。

答案 1 :(得分:1)

我认为你要找的是 Type Erasure 。您可以将其视为接口的反转。您可以将界面想象为坐在类的底部,确定它需要提供哪些方法。一种类型的擦除对象在顶部附加,并“提取”某些方法,引入鸭子类型。有an upcoming Boost Type Erasure library这将使这个易于使用的概念。

以下是它在普通C ++ 11中的工作原理(它也很容易在11 C ++之前工作,但我想要 使用unique_ptr):

#include<iostream>
#include<vector>
#include<list>
#include<memory>
using namespace std;

class Person{};


template <class T>
class TypeErasedBidirectionalIterator {
public:
    virtual void operator++()=0;
    virtual void operator--()=0;
    virtual T& operator*()=0;
};

template <class T, class Iterator> 
class BidirectionalIteratorAdaptor: public TypeErasedBidirectionalIterator<T> {
    Iterator it;
public:
    BidirectionalIteratorAdaptor(Iterator it): it(it){}
    void operator++(){it++;}
    void operator--(){it--;}
    T& operator*(){*it;}
};

template <class Iterator>
unique_ptr<BidirectionalIteratorAdaptor<typename Iterator::value_type,Iterator> > makeIterator(Iterator it) {
    typedef typename Iterator::value_type T;
    return unique_ptr<BidirectionalIteratorAdaptor<T,Iterator> >(new BidirectionalIteratorAdaptor<T,Iterator>(it));
}

typedef TypeErasedBidirectionalIterator<Person> PersonIterator;
typedef unique_ptr<PersonIterator> PersonIteratorPtr;


int main() {
    vector<Person> vec;
    list<Person> lst;
    lst.push_back(Person());
    PersonIteratorPtr it = makeIterator(vec.begin());
    it = makeIterator(lst.begin());
    ++*it;
    --*it;
    **it;
}

请注意,将PersonIteratorPtr包装在另一个公开方法的类中 直接你可以摆脱类似指针的行为,但我不想让概念验证复杂化。