Я ищу контейнерный класс C ++, который оборачивает типизированный массив объектов, которые не обязательно инициализируются и не должны быть конструируемыми по умолчанию или копируемыми. Это было бы интересно для объектов RAII, которые не имеют четко определенной семантики копирования. Такой контейнероподобный класс кажется довольно простым для написания (используя распределитель для выделения неинициализированной памяти и размещения нового). Есть ли что-то подобное в Boost, которое я только что пропустил? Я не ищу std::vector
(который требует, чтобы его элементы были конструируемыми для копирования) или контейнер указателя, но что-то вроде этого:
#include <cstddef>
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
template< typename T, typename Alloc = std::allocator<T> >
class FixedVector {
public:
typedef typename Alloc::value_type value_type;
typedef typename Alloc::pointer pointer;
typedef typename Alloc::reference reference;
typedef typename Alloc::const_pointer const_pointer;
typedef typename Alloc::const_reference const_reference;
typedef typename Alloc::size_type size_type;
typedef typename Alloc::difference_type difference_type;
typedef pointer iterator;
typedef const_pointer const_iterator;
explicit FixedVector(size_type size, const Alloc& allocator = Alloc()):
m_alloc(allocator),
m_size(size),
m_data(m_alloc.allocate(size)),
m_constructed(size) { }
FixedVector(const FixedVector& other):
m_alloc(other.m_alloc),
m_size(other.m_size),
m_data(m_alloc.allocate(m_size)),
m_constructed(other.m_constructed) {
for (size_type i = 0; i != m_size; ++i) {
if (m_constructed[i]) m_alloc.construct(m_alloc.address(m_data[i]), other[i]);
}
}
~FixedVector() {
for (size_type i = 0; i != m_size; ++i) {
if (m_constructed[i]) m_alloc.destroy(m_alloc.address(m_data[i]));
}
m_alloc.deallocate(m_data, m_size);
}
FixedVector& operator=(FixedVector other) {
other.swap(*this);
return *this;
}
// operator[] and other unimportant stuff
void swap(FixedVector& other) {
std::swap(m_alloc, other.m_alloc);
std::swap(m_size, other.m_size);
std::swap(m_data, other.m_data);
std::swap(m_constructed, other.m_constructed);
}
void construct(size_type index) {
new (m_alloc.address(m_data[index])) T();
m_constructed[index] = true;
}
template<typename U>
void construct(size_type index, U& val) {
new (m_alloc.address(m_data[index])) T(val);
m_constructed[index] = true;
}
template<typename U>
void construct(size_type index, const U& val) {
new (m_alloc.address(m_data[index])) T(val);
m_constructed[index] = true;
}
private:
Alloc m_alloc;
size_type m_size;
pointer m_data;
std::vector<bool> m_constructed;
};
template<typename T, typename Alloc>
void swap(FixedVector<T, Alloc>& first, FixedVector<T, Alloc>& second) {
first.swap(second);
}
namespace std {
template<typename T, typename Alloc>
void swap(FixedVector<T, Alloc>& first, FixedVector<T, Alloc>& second) {
first.swap(second);
}
}
class Test {
public:
explicit Test(int val): m_val(val) {
std::cout << "Test::Test(" << val << ')' << std::endl;
}
~Test() {
std::cout << "Test::~Test() [with m_val = " << m_val << ']' << std::endl;
}
int val() const {
return m_val;
}
private:
int m_val;
Test(const Test&);
Test& operator=(const Test&);
};
template<typename Char, typename Traits>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& stream, const Test& object) {
return stream << object.val();
}
int main() {
typedef FixedVector<Test> FVT;
FVT w(10);
w.construct(7, 7);
w.construct(2, 2);
std::cout << "w[2] = " << w[2] << std::endl;
}
Решение должно работать в C ++ 03 (например, семантика перемещения не допускается). Вопрос немного академический - мне просто интересно, почему такого класса в Boost не существует.