#ifndef _GHLIBCPP_ARRAY
#define _GHLIBCPP_ARRAY
#include <iterator>
#include <string>
#include <empty.h>

// Note: a few features currently unused by tests are commented out
namespace std {
template <class T, size_t N> struct array {
  typedef T &reference;
  typedef const T &const_reference;
  typedef __iterator<T> iterator;
  typedef __iterator<const T> const_iterator;
  typedef size_t size_type;

  typedef ptrdiff_t difference_type;
  typedef T value_type;
  typedef T *pointer;
  typedef const T *const_pointer;
  // typedef std::reverse_iterator<iterator> reverse_iterator;
  // typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  T elems[N];
  void fill(const T &u);
  // void swap(array &) noexcept(noexcept(swap(declval<T &>(), declval<T
  // &>())));
  iterator begin() noexcept;
  const_iterator begin() const noexcept;
  iterator end() noexcept;
  const_iterator end() const noexcept;
  // reverse_iterator rbegin() noexcept;
  // const_reverse_iterator rbegin() const noexcept;
  // reverse_iterator rend() noexcept;
  // const_reverse_iterator rend() const noexcept;
  const_iterator cbegin() const noexcept;
  const_iterator cend() const noexcept;
  // const_reverse_iterator crbegin() const noexcept;
  // const_reverse_iterator crend() const noexcept;

  constexpr size_type size() const noexcept;
  constexpr size_type max_size() const noexcept;
  constexpr bool empty() const noexcept;
  reference operator[](size_type n);
  constexpr const_reference operator[](size_type n) const;
  reference at(size_type n);
  constexpr const_reference at(size_type n) const;
  reference front();
  constexpr const_reference front() const;
  reference back();
  constexpr const_reference back() const;
  T *data() noexcept;
  const T *data() const noexcept;
};
} // namespace std

#endif // _GHLIBCPP_ARRAY