2011-04-20 95 views
0

这是可以做到的,如果没有拷贝集装箱的数据?:STL迭代器和模板

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()); 
+2

@samadhi:是*什么*可能没有复制容器的数据? – phooji 2011-04-20 19:19:47

+1

就像我在你的最后一个问题中问的那样:为什么?什么是随机限制来编写异端代码?无论如何,你想要类型擦除。 – GManNickG 2011-04-20 19:21:07

+0

我不明白..您想做什么? – 2011-04-20 19:21:14

回答

1

如果您确实希望能够声明仅与容器中包含的数据类型相关的模板,并且您希望能够将任何类型的迭代器(即迭代器)存储到任何类型的容器),解决方案是在迭代器上执行类型擦除

如果您可以将一些外部库引入到adobe库中,如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 
}; 

的代码片段只用于展览,他们不是生产代码,没有被编译,并有相当数量的不做的(裸指针,迭代器可以成为在任何时候无效在对象的生命周期中...),但是打算给y ou一个想法,你需要在迭代器上执行类型擦除。然后,再看看链接的adobe库,以获得更深思熟虑的提议。

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

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'? 

也就是说,如果是存储在您的类迭代器在所有。大多数时候,你不会。除了在许多情况下迭代器至少在预期时间内失效,这只是一个笨拙的设计。

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; 
    } 
}; 

这并不取决于包含一个typedef其value_type的迭代器类型,这是迭代器标准的容器,如向量和列表也是如此。你可以(可以)编写你自己的迭代器,但它不会这样做,这会使得这样的代码变得不可能(当然这就是标准库的工作方式)。