![](/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.