Следуя этому вопросу, я хочу использовать unitialised_allocator
с, скажем, std::vector
, чтобы избежать инициализации элементов по умолчанию при построении (или resize()
из std::vector
(см. также здесь для использования). Мой текущий проект выглядит следующим образом:
// based on a design by Jared Hoberock
template<typename T, typename base_allocator >
struct uninitialised_allocator : base_allocator::template rebind<T>::other
{
// added by Walter Q: IS THIS THE CORRECT CONDITION?
static_assert(std::is_trivially_default_constructible<T>::value,
"value type must be default constructible");
// added by Walter Q: IS THIS THE CORRECT CONDITION?
static_assert(std::is_trivially_destructible<T>::value,
"value type must be default destructible");
using base_t = typename base_allocator::template rebind<T>::other;
template<typename U>
struct rebind
{
typedef uninitialised_allocator<U, base_allocator> other;
};
typename base_t::pointer allocate(typename base_t::size_type n)
{
return base_t::allocate(n);
}
// catch default construction
void construct(T*)
{
// no-op
}
// forward everything else with at least one argument to the base
template<typename Arg1, typename... Args>
void construct(T* p, Arg1 &&arg1, Args&&... args)default_
{
base_t::construct(p, std::forward<Arg1>(arg1), std::forward<Args>(args)...);
}
};
Затем шаблон unitialised_vector<>
можно определить следующим образом:
template<typename T, typename base_allocator = std::allocator<T>>
using uninitialised_vector =
std::vector<T,uninitialised_allocator<T,base_allocator>>;
Однако, как указано в моих комментариях, я не уверен на 100% относительно каковы соответствующие условия в static_assert()
? (Btw, вместо этого можно рассматривать SFINAE - любые полезные комментарии к этому приветствуются)
Очевидно, нужно избегать катастрофы, которая возникла бы при попытке нетривиального уничтожения неинициализированного объекта. Рассмотрим
unitialised_vector< std::vector<int> > x(10); // dangerous.
Было высказано предположение (комментарий Евгения Панасюка), что я утверждаю тривиальную конструктивность, но это, похоже, не улавливает вышеупомянутый сценарий бедствия. Я просто попытался проверить, что говорит clang о std::is_trivially_default_constructible<std::vector<int>>
(или std::is_trivially_destructible<std::vector<int>>
), но все, что я получил, было сбой clang 3.2...
Другим, более продвинутым вариантом будет создание распределителя, который только лишает конструкцию по умолчанию для объектов, для которых это было бы безопасно.