一种可能的解决方案是创建您自己的Allocator。std::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)
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |