2

无论设计是否良好,我的方法都声明了一个变量,该变量需要根据正在使用的数据结构(由输入参数确定)main()来预期满足BidirectionalIterator定义(特别是list<>::iteratoror )的任何迭代器。vector::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 语句来存储迭代器并使用我想要的迭代器。

4

2 回答 2

1

我认为您正在寻找的是Type Erasure。您可以将其视为接口的反面。您可以将接口想象为位于类的底部,确定它需要提供哪些方法。类型擦除对象在顶部附加,并“提取”某些方法,引入鸭子类型。即将推出的Boost Type Erasure 库将使它成为一个易于使用的概念。

以下是它在普通 C++11 中的工作方式(它也可以很容易地在 pre-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另一个直接公开方法的类包装在内部,您可以摆脱类似指针的行为,但我不想让概念验证更加复杂。

于 2013-02-18T05:40:44.060 回答
1

听起来你想要typedef:

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

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

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

于 2013-02-18T05:12:31.373 回答