![](/img/trans.png)
[英]How to define the type of a member of an iterator class to work with STL container methods?
[英]Define an iterator type in a stl container wrapper
在STL容器周围编写包装类的正确方法是什么,它也是一个模板(可以接受泛型类型T作为元素)并允许我像直接使用STL容器一样使用迭代器?
我想做以下类型的事情
#include <list>
#include <iostream>
class MyClass{};
template<class T>
class Wrapper
{
public:
typename std::list<T>::iterator iterator;
std::list<T> elements;
iterator begin(){ return elements.begin(); };
iterator end(){ return elements.end(); };
};
int main()
{
Wrapper<MyClass> wrapper;
for (Wrapper::iterator it = wrapper.begin(); it != wrapper.end(); ++it)
std::cout<<"Hi"<<std::endl;
}
但是编译器说:
error: ‘iterator’ in ‘class Wrapper<T>’ does not name a type
你有两个错误。
就像Igor Tandetnik在评论中所说,你的iterator
是一个数据成员,而不是你的案例的嵌套类型。
你必须在班上这样做:
typedef typename std::list<T>::iterator iterator;
或者,在C ++ 11中:
using iterator = typename std::list<T>::iterator;
此外,您在main()
代码中使用错误的方式使用iterator
。 它应该是这样的:
Wrapper<MyClass>::iterator it = wrapper.begin()
或者,在C ++ 11或更高版本中,您可以这样做:
for(const auto &element : wrapper) {
...
}
就个人而言,我更喜欢使用私有继承而不是封装。 在我的脑海中,公共继承意味着“IS A”关系,而私人继承意味着“实施中的关系”。
你可以这样做:
template<typename T>
class WrapperList : private List<T> {
... Your code that belongs to your wrapper
}
如果你想包装std :: list并通过一些功能来丰富它,实际上,在包装器中维护一些(或大多数)std :: list接口(作为迭代功能),还有(至少)两个可能性。
一个(组合)是在包装器中定义begin(),end()方法和迭代器类型,以便将它们传播到包含的结构,如Andrea Araldo所提出的。
一个(私有继承)是利用私有继承,在某些情况下这可能非常方便。 需要的步骤:
例如,在下文中,在这个意义上(WrapperPrivInh)对所提出的片段进行了略微修改。 在这种情况下,std :: list的所有标准构造函数都可以在包装器接口中免费获得。 此外,为了完整性,还提出了WrapperCompos变体,其中列表包含在包装器中,它公开了支持基于迭代器的循环所需的内容。 在这种情况下,只从头开始重新定义“默认元素数量”构造函数。
#include <list>
#include <iostream>
class MyClass
{
public:
MyClass() { std::cout<<"(DEBUG)MyClass::default constructor\n"; }
};
template<class T>
class WrapperPrivInh : private std::list<T>
{
public:
using std::list<T>::iterator; //for the iterator type
using std::list<T>::begin; // for the begin()
using std::list<T>::end; // and end() methods
using std::list<T>::list; // for the constructors, if needed
//std::list<T> elements;
//iterator begin(){ return elements.begin(); };
//iterator end(){ return elements.end(); };
};
template<class T>
class WrapperCompos
{
std::list<T> m_list;
public:
using iterator= typename std::list<T>::iterator; //for the iterator type
WrapperCompos(int const n) : m_list(n) { }
iterator begin(){ return m_list.begin(); };
iterator end(){ return m_list.end(); };
};
int main()
{
{
std::cout<<"Experiment with private inheritance"<<'\n';
WrapperPrivInh<MyClass> wrapper(3); // constructor witch builds N (3 here) MyClass default elements (derived "for free" from std::list)
for(WrapperPrivInh<MyClass>::iterator it = wrapper.begin(); it != wrapper.end(); ++it)
std::cout<<"Hi "<<&(*it)<<std::endl;
}
{
std::cout<<"\nExperiment with private inheritance"<<'\n';
WrapperCompos<MyClass> wrapper(3); // constructor witch builds N (3 here) MyClass default elements (derived "for free" from std::list)
for(WrapperCompos<MyClass>::iterator it = wrapper.begin(); it != wrapper.end(); ++it)
std::cout<<"Hi "<<&(*it)<<std::endl;
for( auto const& x : wrapper ) //range-for-loop syntax (from c++11)
std::cout<<"Hi2 "<<&x<<std::endl;
}
}
私有继承方法可以很容易地,并且正确地将包装结构的特征传播到包装器。 例如,如果包装结构与它们兼容,则包装器可以很容易地与std :: algorithms兼容,就像std :: list一样。 希望这可以帮助。 最好
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.