【发布时间】:2015-08-04 21:44:24
【问题描述】:
我需要擦除不同 stl 的元素并通过迭代器提升容器。有时我还需要使用 reverse_iterator 来做到这一点,所以我想将它包装到一个通用函数(集合)中。
据此: Iterator invalidation rules 应该是可能的。
到目前为止,我得到的是:
template<class T, bool T_IterReturned = helpers::EraseReturnsIterator<T>::value>
struct EraseImpl
{
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
static iterator erase(list& container, iterator it) {
return container.erase(it);
}
static const_iterator erase(list& container, const_iterator it) {
return container.erase(it);
}
};
template<class T>
struct EraseImpl<T, false>
{
// This one gets used for e.g. std::set whos erase does not return
// an iterator until C++11
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
static iterator erase(list& container, iterator it) {
container.erase(it++);
return it;
}
static const_iterator erase(list& container, const_iterator it) {
container.erase(it++);
return it;
}
};
template<typename T>
inline typename T::iterator erase(T& container, typename T::iterator it)
{
return detail::EraseImpl<T>::erase(container, it);
}
template<typename T>
inline typename T::reverse_iterator erase(T& container, typename T::reverse_iterator it)
{
typename T::reverse_iterator tmp = it;
return typename T::reverse_iterator(erase(container, (++tmp).base()));
}
这应该适用于大多数情况,但例如不返回迭代器的类向量容器会破坏这一点。集合不会使任何其他迭代器无效-> 可以使用下一个迭代器。对于向量,我需要存储前一个迭代器(如果有的话)并返回它。对于没有迭代器返回的双端队列(和类似的),这根本不起作用。我不想为所有已知容器实现 EraseImpl,例如这将要求我包含我想要避免的所有标题。
有什么办法可以避免专门针对所有类型吗?当然,我可以使用 {Use_Next, Use_Prev} 之类的枚举创建一个特征,并将其非专门用于使所有迭代器无效的容器。但同样:我不想包含所有可能的标题。
【问题讨论】:
-
你不需要包含所有的标题,前向声明就足够了。
-
@Jarod42:您不能前向声明标准库类型。这就是为什么有一个特殊的
<iosfwd>。然而,这是唯一这样的标题。 -
我怀疑没有通用的解决方案。您将如何处理使
erase上的所有 迭代器无效的容器?没那么牵强;收缩的类似矢量的容器可能会这样做。 (重新分配到更小的区块) -
@MSalters:对于假设的类向量,您仍然可以将索引保存并重新创建迭代器为
container.begin() + index... 但我同意处理每个奇怪的情况需要做很多工作。 (我想知道迭代器容器可能对哪个要求较低)。 -
然后可能有额外的包含文件用于非迭代器返回容器,其中包含容器包含并定义特征。然后包括那些而不是原来的?反正看起来很丑……
标签: c++ stl iterator erase invalidation