【问题标题】:Generic erase function通用擦除功能
【发布时间】: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:您不能前向声明标准库类型。这就是为什么有一个特殊的&lt;iosfwd&gt;。然而,这是唯一这样的标题。
  • 我怀疑没有通用的解决方案。您将如何处理使erase 上的所有 迭代器无效的容器?没那么牵强;收缩的类似矢量的容器可能会这样做。 (重新分配到更小的区块)
  • @MSalters:对于假设的类向量,您仍然可以将索引保存并重新创建迭代器为container.begin() + index... 但我同意处理每个奇怪的情况需要做很多工作。 (我想知道迭代器容器可能对哪个要求较低)。
  • 然后可能有额外的包含文件用于非迭代器返回容器,其中包含容器包含并定义特征。然后包括那些而不是原来的?反正看起来很丑……

标签: c++ stl iterator erase invalidation


【解决方案1】:

我目前使用的解决方案是使用可以为每个容器类专门化的特征类。

默认为“不允许”,但也为具有擦除功能的容器提供专门化,该功能返回一个迭代器。这是以通用方式完成的,因此仅检查此类函数的存在。如果找到,generic_erase 使用它。如果不是,则 trait 会询问用户对迭代器(next_iterator_valid、prev_iterator_valid、all_invalid)做了什么擦除,然后 generic_erase 会相应地进行操作。

这对这项任务很有帮助:Check for function signature also for inherited functions

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-04
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 2020-08-08
    • 2014-03-17
    相关资源
    最近更新 更多