我可以限制 C++14 Vector 的大小吗?

Maw*_*awg 6 c++ c++14

正如图块所示,我是否可以在 C++ 14 中声明一个向量并限制它可以容纳的最大条目数?

Ted*_*gmo 8

一种可能的解决方案是创建您自己的Allocatorstd::allocator是无状态的,但您可以实现max_size()成员函数,该函数应返回携带最大元素数的成员变量的值。

一个适用于 C++11 直到至少 C++20 的示例:

template<class T>
struct limited_allocator : public std::allocator<T> {
    using value_type = typename std::allocator<T>::value_type;
    using size_type = typename std::allocator<T>::size_type;
    using difference_type = std::ptrdiff_t;
    using propagate_on_container_move_assignment = std::true_type;

    using is_always_equal = std::false_type; // not needed since C++23

#if __cplusplus < 201703L
    using pointer = typename std::allocator<T>::pointer;
    using const_pointer = typename std::allocator<T>::const_pointer;
    using reference = typename std::allocator<T>::reference;
    using const_reference = typename std::allocator<T>::const_reference;

    template<class U> struct rebind {
        typedef limited_allocator<U> other;
    };
#endif
    
    // No default constructor - it needs a limit:
    constexpr limited_allocator(size_type max_elements) noexcept :
        m_max_elements(max_elements) {}

    constexpr limited_allocator( const limited_allocator& other ) noexcept = default;

    template< class U >
    constexpr limited_allocator( const limited_allocator<U>& other ) noexcept :
        m_max_elements(other.m_max_elements) {}

    // Implementing this is what enforces the limit:
    size_type max_size() const noexcept { return m_max_elements; }

private:
    size_type m_max_elements;
};
Run Code Online (Sandbox Code Playgroud)

由于此分配器不是无状态的,因此您最好也实现非成员比较函数:

template< class T1, class T2 >
constexpr bool operator==(const limited_allocator<T1>& lhs,
                          const limited_allocator<T2>& rhs ) noexcept {
    return &lhs == &rhs;
}

template< class T1, class T2 >
constexpr bool operator!=(const limited_allocator<T1>& lhs,
                          const limited_allocator<T2>& rhs ) noexcept {
    return &lhs != &rhs;
}
Run Code Online (Sandbox Code Playgroud)

一个用法示例,其中只vector允许保留1元素:

int main() {
    std::vector<int, limited_allocator<int>> vec(limited_allocator<int>(1));
//                   ^^^^^^^^^^^^^^^^^^^^^^      ^^^^^^^^^^^^^^^^^^^^^^^^^
    try {
        vec.push_back(1);   // one element
        vec.pop_back();     // zero again
        vec.push_back(2);   // one again
        vec.push_back(3);   // here it'll throw
    }
    catch(const std::length_error& ex) {
        std::cout << "length_error: " << ex.what() << '\n';
    }    
    catch(const std::bad_array_new_length& ex) {
        std::cout << "bad_array_new_length: " << ex.what() << '\n';
    }
    catch(const std::bad_alloc& ex) {
        std::cout << "bad_alloc: " << ex.what() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

可能的输出:

length_error: vector::_M_realloc_insert
Run Code Online (Sandbox Code Playgroud)

演示