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

时间:2018-10-10 18:23:31

标签: c++ templates

我想创建一个模板类,该模板类具有STL容器的迭代器作为成员。那就是我走了多远:

#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. 您能解释一下语法template <typename> class StdLibContainer吗? 我在stackoverflow上的某个地方找到了它。但是我不明白。

  2. 如何创建ClassHoldingAnIteratorToAStandardContainer的实例?到目前为止,我所有的尝试都失败了。编译器总是给出错误消息:`期望一个类模板,得到了'std :: vector'

在上面的示例中,我想分配holding_iterator_to_vec vec.begin()

2 个答案:

答案 0 :(得分:1)

template <typename> classtemplate <class> class相同。最初,引入模板时,它们允许两种等效形式:

template<class T> struct Foo {};
// or
template<typename T> struct Foo {};

不要问我为什么!但是,对于模板模板参数,情况并非如此:

template <template <class> typename T> struct Foo {};

是唯一允许的语法。显然,人们对此感到不满意,因此语法放松了。

关于第二个问题,std::vector至少使用两个模板参数,数据类型和分配器。这就是为什么单个参数模板不会在C ++ 17之前删除它的原因。在C ++ 17之后,它将起作用。

要使其通用,请使用

template<template <class...> class Container> struct Foo{};

答案 1 :(得分:0)

除非您真的需要了解容器的类型,否则我强烈建议使ClassHoldingAnIteratorToAStandardContainer与具体的容器类型无关。如果您只需要迭代器,这将更加简单和充分:

template<typename iterator>
struct iterator_wrapper {
    iterator iter;    
};

那是您需要拥有迭代器作为成员的最低要求:)。

我真的不知道您要使用迭代器做什么,所以仅出于示例的目的,让我们添加实际使用迭代器的方法。...

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

}

您的代码中也有问题。

typename StdLibContainer<Element*>::iterator

用于指针容器,而在主容器中则有int个。如果要从容器类型推断出迭代器类型,则可以这样进行操作:

template <typename container, 
          typename iterator = typename container::iterator>
iterator_wrapper<iterator> wrap_begin(container& c) { 
    return {c.begin()}; 
}

这使得创建iterator_wrapper变得如此简单

auto x = wrap_begin(vec);

请注意,此答案适用于C ++ 11,在较新的标准中,有推论指南使此类make_x方法或多或少成为多余的afaik。