没有复制容器的数据可以做到这一点吗?:
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());
答案 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::function
或boost::any
相同的方法。其中一个优点是,您可以在不同情况下使用相同的Foo
类与不同的迭代器系列。另一方面,它需要动态调度,但在大多数情况下这不应该是有问题的。