简体   繁体   English

带有迭代器的模板类到STL容器

[英]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;
}
  1. 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. 但是我不明白。

  2. 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> classtemplate <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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM