STL迭代器和模板

时间:2011-04-20 19:12:22

标签: c++ stl iterator containers

没有复制容器的数据可以做到这一点吗?:

template<typename T> //we know only the type return by iterator
class Foo {
private:
    I b; //or some base class of iterator or own generic iterator
    I e; //what should be 'I'?
public:
    template<typename I>
    Foo(begin, end) {
        b = begin;
        e = end;
    }
    void find(T value) {
        while(b != e) {
            ...
            ++b;
        }
        return NULL;
    }
};
//...
//this can't be changed
std::vector<int> vec;
Foo<int> foo1(vec.begin(), vec.end());
std::list<double> list;
Foo<double> foo2(list.begin(), list.end());

3 个答案:

答案 0 :(得分:2)

考虑到你试图调用构造函数的方式:

std::vector<int> vec;
Foo<int> foo1(vec.begin(), vec.end());
std::list<double> list;
Foo<double> foo2(list.begin(), list.end());

...你会这样做:

template<typename Iter> //we know only the type return by iterator
class Foo {
private:
    Iter b; //or some base class of iterator or own generic iterator
    Iter e; //what should be 'I'?

也就是说, if 你根本就在你的班级存储了一个迭代器。大多数时候,你不会。除了在很多情况下迭代器可以在至少预期的时间内失效,这只是一个笨拙的设计。

答案 1 :(得分:1)

您的代码似乎没有多大意义。我倾向于同意GMan,你想要做的事情可能没用。然而,有些模糊相似的事情是有道理的。当它们这样做时,通常使用迭代器类型作为模板参数:

template<class inIt> 
class Foo { 
    inIt begin;
    inIt end;
public:
    Foo(inIt b, inIt e) : begin(b), end(e) {}
    bool find(typename inIt::value_type v) { 
        while (b!=e) {
           if (*b == v)
               return true;
            ++b;
        }
        return false;
    }
};

这取决于包含其value_type的typedef的迭代器类型,对于像vector和list这样的标准容器的迭代器也是如此。您可以(可以)编写自己的迭代器,但这样做不会这样做,这会使得这样的代码几乎不可能(当然,这就是标准库按照它的方式工作的原因)。

答案 2 :(得分:1)

如果您真的希望能够仅根据容器中包含的数据类型声明模板,同时您希望能够存储任何类型的迭代器(即迭代器到任何类型的容器中),解决方案是在迭代器上执行类型擦除

如果你可以带一些外部库,那就已经在adobe libs中完成了any_iterator。基本上,您定义了一个基类,它定义了动态多态(即虚方法)所需的迭代器接口,然后使用采用适当类型的模板实现该接口:

template <typename T>
struct any_iterator {
   // all typedefs for an iterator here, including:
   typedef T value_type;

   virtual ~any_iterator() {}
   virtual any_iterator& operator++() = 0;
   virtual value_type& operator*() = 0;
   // ... rest of the methods
};
template <typename Iterator>
class any_iterator_impl : any_iterator< typename Iterator::value_type > {
   iterator it;
public:
   // all the typedefs
   typedef Iterator iterator;
   typedef typename iterator::value_type value_type;

   // actual implementation of the interface
   any_iterator_impl( Iterator it ) : it(it) {}
   virtual any_iterator_impl& operator++() { ++it; return *this; }
   virtual value_type& operator*() { return *it; }
   // ... and all the rest of the interface
};

然后在课堂上使用它:

template <typename T>
class Foo {
   std::unique_ptr<any_iterator> it, end; // in real code use smart pointers here
public:
   template <typename Iterator>
   Foo( Iterator b, Iterator e ) {
      static_assert( is_same< typename Iterator::value_type, T>::value );
      it = new any_iterator_impl<Iterator>( begin );
      end = new any_iterator_impl<Iterator>( end );
   }
   // rest of the class
};

代码片段仅用于展览,它们不是生产代码,尚未编译并且有相当数量的不执行(原始指针,迭代器在任何时候都可能无效)对象的生命周期...),但旨在让您了解在迭代器上执行类型擦除所需的工作。然后,再看一下链接的adobe库,以获得更深思熟虑的提案。

如果您对此感到好奇,则采用与std::functionboost::any相同的方法。其中一个优点是,您可以在不同情况下使用相同的Foo类与不同的迭代器系列。另一方面,它需要动态调度,但在大多数情况下这不应该是有问题的。