[英]Template class with iterator to a STL container
I want to create a template class which has an iterator of a STL container as a member. 我想创建一个模板类,该模板类具有一个STL容器的迭代器作为成员。 That is how far I got: 那是我走了多远:
#include <iostream>
#include <vector>
using namespace std;
template<typename Element, template <class> class StdLibContainer>
struct ClassHoldingAnIteratorToAStandardContainer
{
ClassHoldingAnIteratorToAStandardContainer(){}
typename StdLibContainer<Element*>::iterator std_lib_iterator;
};
int main()
{
vector<int> vec{1,2,3};
ClassHoldingAnIteratorToAStandardContainer<int,vector<int>> holding_iterator_to_vec;
//DOES NOT WORK, compiler says: expected a class template, got ‘std::vector<int>’
return 0;
}
Could you explain the syntax template <typename> class StdLibContainer
? 您能解释语法template <typename> class StdLibContainer
吗? I found it somewhere on stackoverflow. 我在stackoverflow上的某个地方找到了它。 BUt I don't understand it. 但是我不明白。
How can I create an instance of ClassHoldingAnIteratorToAStandardContainer
? 如何创建ClassHoldingAnIteratorToAStandardContainer
的实例? All my attempts failed so far. 到目前为止,我所有的尝试都失败了。 The compiler always gives the error message: `expected a class template, got 'std::vector' 编译器总是给出错误信息:`期望一个类模板,得到了'std :: vector'
In the above example i want to assign holding_iterator_to_vec
vec.begin()
. 在上面的示例中,我想分配holding_iterator_to_vec
vec.begin()
。
template <typename> class
is the same as template <class> class
. template <typename> class
与template <class> class
。 Originally, when templates were introduced, they allowed two equivalent forms: 最初,引入模板时,它们允许两种等效形式:
template<class T> struct Foo {};
// or
template<typename T> struct Foo {};
Do not ask me why! 别问我为什么! However, the same was not true for template template parameters: 但是,对于模板模板参数,情况并非如此:
template <template <class> typename T> struct Foo {};
was the only allowed syntax. 是唯一允许的语法。 Apparently, people were unhappy about it, so the syntax was relaxed. 显然,人们对此不满意,因此语法变得轻松。
As for your second question, std::vector
takes at least two template arguments, data type and allocator. 至于第二个问题, std::vector
至少接受两个模板参数,数据类型和分配器。 This is why a single argument template doesn't cut it before C++17. 这就是为什么单个参数模板不会在C ++ 17之前删除它的原因。 After C++17, it would work. 在C ++ 17之后,它将起作用。
To make it universal, use 为了使其通用,请使用
template<template <class...> class Container> struct Foo{};
Unless you really need to know the type of the container, I would strongly recommend to keep your ClassHoldingAnIteratorToAStandardContainer
independent of the concrete container type. 除非您真的需要知道容器的类型,否则我强烈建议您使ClassHoldingAnIteratorToAStandardContainer
与具体的容器类型无关。 If you just need the iterator, this is simpler and sufficient: 如果只需要迭代器,这将更加简单和充分:
template<typename iterator>
struct iterator_wrapper {
iterator iter;
};
Thats the minimum you need to have an iterator as member :). 这就是您需要将迭代器作为成员的最低要求:)。
I dont really know what you want to use the iterator for, so just for the sake of an example lets add methods that actually use the iterator.... 我真的不知道您要使用迭代器做什么,所以仅出于示例的目的,让我们添加实际使用迭代器的方法。
#include <iterator>
#include <vector>
#include <iostream>
template<typename iterator>
struct iterator_wrapper {
using value_type = typename std::iterator_traits<iterator>::value_type;
iterator iter;
bool operator!=(const iterator& other) { return iter != other;}
iterator_wrapper& operator++(){
++iter;
return *this;
}
const value_type& operator*() { return *iter; }
};
template <typename iterator>
iterator_wrapper<iterator> wrap_iterator(iterator it) {
return {it};
}
int main() {
std::vector<int> vec{1,2,3};
auto it = wrap_iterator(vec.begin());
for (;it != vec.end();++it) std::cout << *it;
} }
Also there is a problem in your code. 您的代码中也有问题。
typename StdLibContainer<Element*>::iterator
is for containers of pointers while in main you have int
s. 用于指针容器,而在main中则具有int
。 If you want to infer the iterator type from the container type then you can do it for example like this: 如果要从容器类型推断出迭代器类型,则可以例如这样进行操作:
template <typename container,
typename iterator = typename container::iterator>
iterator_wrapper<iterator> wrap_begin(container& c) {
return {c.begin()};
}
which makes creating an iterator_wrapper
as simple as 这使得创建iterator_wrapper
的过程非常简单
auto x = wrap_begin(vec);
Note that this answer applies to C++11, in newer standards there are deduction guides that make such make_x
methods more or less superfluous afaik. 请注意,此答案适用于C ++ 11,在较新的标准中,有推论指南使make_x
方法或多或少成为多余的afaik。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.