I have implemented an Array class using templates. I have used a std::allocator object for memory allocation. Will it be better to use operator new along with placement new for memory allocation?
array.h
#ifndef ARRAY_H
#define ARRAY_H
#include <memory>
#include <cstddef>
template <typename T> class Array;
template<typename T> void swap(Array<T> &first, Array<T> &second);
template <typename T> class Array {
friend void swap <> (Array<T> &first, Array<T> &second);
public:
typedef T *iterator;
typedef const T *const_iterator;
typedef std::size_t size_type;
typedef T value_type;
explicit Array(size_type size, const T& value = T());
Array(const_iterator range_begin, const_iterator range_end);
Array(const Array&);
Array& operator=(const Array);
size_type size() const;
T& operator[](size_type i);
const T& operator[](size_type i) const;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
~Array();
private:
iterator data; // points to the first element of the array
iterator limit; // points to one past the last element
iterator avail; // points to one past the allocated memory
std::allocator<T> alloc; // for memory allocation
};
// implementation
#include <algorithm>
template<typename T> void swap(Array<T> &first, Array<T> &second)
{
using std::swap;
swap(first.data, second.data);
swap(first.limit, second.limit);
swap(first.avail, second.avail);
}
template<typename T> Array<T>::Array(size_type size, const T& value):
data(alloc.allocate(size)), limit(data), avail(data + size)
{
while (limit < data + size)
alloc.construct(limit++, value);
}
template<typename T> Array<T>::Array(const_iterator range_begin,
const_iterator range_end):
data(alloc.allocate(range_end - range_begin)), limit(data),
avail(data + range_end - range_begin)
{
const_iterator it = range_begin;
while (limit < data + range_end - range_begin) {
alloc.construct(limit++, *it);
++it;
}
}
template<typename T> Array<T>::Array(const Array &original):
data(alloc.construct(original.size())), limit(data),
avail(data + original.size)
{
iterator it = original.begin();
while (it != original.limit()) {
alloc.construct(limit++, *it);
++it;
}
}
template<typename T> Array<T>& Array<T>::operator=(const Array rhs)
{
swap(*this, rhs);
return *this;
}
template<typename T> typename Array<T>::size_type Array<T>::size() const
{
return limit - data;
}
template<typename T> T& Array<T>::operator[](size_type i)
{
return data[i];
}
template<typename T> const T& Array<T>::operator[](size_type i) const
{
return data[i];
}
template<typename T> typename Array<T>::iterator Array<T>::begin()
{
return data;
}
template<typename T> typename Array<T>::const_iterator Array<T>::begin() const
{
return data;
}
template<typename T> typename Array<T>::iterator Array<T>::end()
{
return limit;
}
template<typename T> typename Array<T>::const_iterator Array<T>::end() const
{
return limit;
}
template<typename T> Array<T>::~Array()
{
while (limit != data)
alloc.destroy(--limit);
alloc.deallocate(data, avail - data);
}
#endif
dynarray
. It was a container type proposed for C++14 (n3662) but got shifted to the array extensions TS before being abandoned. \$\endgroup\$