How to check whether a container is stable

前端 未结 1 1181
情书的邮戳
情书的邮戳 2021-01-04 02:56

std::vector is an unstable container, i.e. by resizing the vector, iterators might become invalidated. In contrast, std::list or boost::conta

相关标签:
1条回答
  • 2021-01-04 03:21

    I don't think there is anything available providing such information, but you could write your own trait. However, you will need to specialize it for every stable container that may be used, which is perhaps not an option.

    #include <boost/container/vector.hpp>
    
    #include <iostream>
    #include <type_traits>
    #include <list>
    #include <vector>
    
    template <template <typename...> class Container>
    struct is_stable
        : std::false_type
    {};
    
    template <>
    struct is_stable<std::list>
        : std::true_type
    {};
    
    template <>
    struct is_stable<boost::container::stable_vector>
        : std::true_type
    {};
    
    template<template <typename...> class Container = std::list>
    class Foo
    {
        static_assert(is_stable<Container>::value, "Container must be stable");
    };
    
    int main()
    {
        Foo<std::list> f1; // ok
        Foo<std::vector> f2; // compiler error
    }
    

    I don't think there is a way you can automatically detect that a container is stable, without resorting to manual specialization.


    Just for fun, I tried writing what the concept/axiom for stability would look like (concepts and axioms are an extension to the language that were considered for inclusion in C++11):

    concept StableGroup<typename C, typename Op>
        : Container<C>
    {
        void operator()(Op, C, C::value_type);
    
        axiom Stability(C c, Op op, C::size_type index, C::value_type val)
        {
            if (index <= c.size())
            {
                auto it = std::advance(c.begin(), index);
                op(c, val);
                return it;
            }
            <->
            if (index <= c.size())
            {
                op(c, val);
                return std::advance(c.begin(), index);
            }
        }
    }
    

    If think this correctly captures the requirement that every iterator over the original container is equivalent to the corresponding iterator over the modified container. Not sure this is very useful, but coming up with such axioms is an interesting exercise :)!

    0 讨论(0)
提交回复
热议问题