我现在已经使用C#了一段时间,回到C ++很头疼。我试图从C#中获取一些我的C ++实践,但我发现了一些阻力,我很乐意接受你的帮助。
我想为这样的类公开迭代器:
template <class T>
class MyContainer
{
public:
// Here is the problem:
// typedef for MyIterator without exposing std::vector publicly?
MyIterator Begin() { return mHiddenContainerImpl.begin(); }
MyIterator End() { return mHiddenContainerImpl.end(); }
private:
std::vector<T> mHiddenContainerImpl;
};
我是否尝试过不是问题的事情?我应该只是输入std :: vector&lt; T&gt; :: iterator?我希望只依赖于迭代器,而不是实现容器......
答案 0 :(得分:18)
您可能会发现以下文章很有趣,因为它完全解决了您发布的问题:On the Tension Between Object-Oriented and Generic Programming in C++ and What Type Erasure Can Do About It
答案 1 :(得分:2)
之前我已经完成了以下操作,因此我得到了一个独立于容器的迭代器。这可能是一种矫枉过正,因为我也可以使用API,其中调用者传入vector<T*>&
,其中应填充所有元素,然后调用者可以直接从向量迭代。
template <class T>
class IterImpl
{
public:
virtual T* next() = 0;
};
template <class T>
class Iter
{
public:
Iter( IterImpl<T>* pImpl ):mpImpl(pImpl) {};
Iter( Iter<T>& rIter ):mpImpl(pImpl)
{
rIter.mpImpl = 0; // take ownership
}
~Iter() {
delete mpImpl; // does nothing if it is 0
}
T* next() {
return mpImpl->next();
}
private:
IterImpl<T>* mpImpl;
};
template <class C, class T>
class IterImplStl : public IterImpl<T>
{
public:
IterImplStl( C& rC )
:mrC( rC ),
curr( rC.begin() )
{}
virtual T* next()
{
if ( curr == mrC.end() ) return 0;
typename T* pResult = &*curr;
++curr;
return pResult;
}
private:
C& mrC;
typename C::iterator curr;
};
class Widget;
// in the base clase we do not need to include widget
class TestBase
{
public:
virtual Iter<Widget> getIter() = 0;
};
#include <vector>
class Widget
{
public:
int px;
int py;
};
class Test : public TestBase
{
public:
typedef std::vector<Widget> WidgetVec;
virtual Iter<Widget> getIter() {
return Iter<Widget>( new IterImplStl<WidgetVec, Widget>( mVec ) );
}
void add( int px, int py )
{
mVec.push_back( Widget() );
mVec.back().px = px;
mVec.back().py = py;
}
private:
WidgetVec mVec;
};
void testFn()
{
Test t;
t.add( 3, 4 );
t.add( 2, 5 );
TestBase* tB = &t;
Iter<Widget> iter = tB->getIter();
Widget* pW;
while ( pW = iter.next() )
{
std::cout << "px: " << pW->px << " py: " << pW->py << std::endl;
}
}
答案 2 :(得分:1)
这应该做你想要的:
typedef typename std::vector<T>::iterator MyIterator;
每当你有一个类型,例如
vector<T>
,取决于模板参数,并且你想使用该类型的成员,例如size_type
,它本身就是一个类型,你必须在typename
之前在整个名称之前让实现知道将名称视为类型。
答案 3 :(得分:1)
我不确定你的意思是“不公开暴露std :: vector”但实际上,你可以像这样定义你的typedef:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator; // To work with constant references
您可以在以后更改这些typedef,而无需用户注意任何内容......
顺便说一句,如果你希望你的类表现为一个容器,那么也应该公开一些其他类型:
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::difference_type difference_type;
typedef typename std::vector<T>::pointer pointer;
typedef typename std::vector<T>::reference reference;
如果你的班级需要的话:
typedef typename std::vector<T>::const_pointer const_pointer;
typedef typename std::vector<T>::const_reference const_reference;
你会在这里找到所有这些typedef的含义:STL documentation on vectors
修改:根据评论
中的建议添加了typename