Advertisement
Radfler

std::array

Apr 28th, 2016
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.26 KB | None | 0 0
  1. #ifndef STDLIB_ARRAY_HPP
  2. #define STDLIB_ARRAY_HPP
  3.  
  4. #include <algorithm>
  5. #include <cstddef>
  6. #include <initializer_list>
  7. #include <iterator>
  8. #include <stdexcept>
  9. #include <type_traits>
  10. #include <utility>
  11.  
  12. namespace stdlib {
  13.  
  14.     using std::size_t;
  15.  
  16.     namespace details {
  17.  
  18.         using std::swap; // for array_traits::is_nothrow_swappable_v
  19.  
  20.         template<typename ValueType, size_t Size>
  21.         struct array_traits {
  22.  
  23.             using type = ValueType[Size];
  24.  
  25.             using iterator = ValueType*;
  26.             using const_iterator = const ValueType*;
  27.  
  28.             static constexpr bool is_nothrow_swappable_v =
  29.                 noexcept(swap(std::declval<ValueType&>(), std::declval<ValueType&>()));
  30.  
  31.             static constexpr iterator begin(type& array) noexcept {
  32.                 return array;
  33.             }
  34.  
  35.             static constexpr const_iterator begin(const type& array) noexcept {
  36.                 return array;
  37.             }
  38.  
  39.             static constexpr iterator end(type& array) noexcept {
  40.                 return array + Size;
  41.             }
  42.  
  43.             static constexpr const_iterator end(const type& array) noexcept {
  44.                 return array + Size;
  45.             }
  46.  
  47.         };
  48.  
  49.         template<typename ValueType>
  50.         struct array_traits<ValueType, 0> {
  51.            
  52.             using type = struct { };
  53.  
  54.             using iterator = ValueType*;
  55.             using const_iterator = const ValueType*;
  56.  
  57.             static constexpr bool is_nothrow_swappable_v = true;
  58.  
  59.             static constexpr iterator begin(type&) noexcept {
  60.                 return nullptr;
  61.             }
  62.  
  63.             static constexpr const_iterator begin(const type&) noexcept {
  64.                 return nullptr;
  65.             }
  66.  
  67.             static constexpr iterator end(type&) noexcept {
  68.                 return nullptr;
  69.             }
  70.  
  71.             static constexpr const_iterator end(const type&) noexcept {
  72.                 return nullptr;
  73.             }
  74.  
  75.         };
  76.  
  77.     }
  78.  
  79.     template<typename ValueType, size_t Size>
  80.     struct array {
  81.  
  82.     private:
  83.  
  84.         using array_traits = ::stdlib::details::array_traits<ValueType, Size>;
  85.  
  86.     public:
  87.  
  88.         using value_type = ValueType;
  89.         using reference = value_type&;
  90.         using const_reference = const value_type&;
  91.        
  92.         using pointer = value_type*;
  93.         using const_pointer = const value_type*;
  94.  
  95.         using iterator = typename array_traits::iterator;
  96.         using const_iterator = typename array_traits::const_iterator;
  97.  
  98.         static_assert(std::is_same<iterator, pointer>::value &&
  99.                       std::is_same<const_iterator, const_pointer>::value,
  100.                       "array::iterator and array::pointer shall be same type");
  101.  
  102.         using reverse_iterator = std::reverse_iterator<iterator>;
  103.         using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  104.  
  105.         using size_type = size_t;
  106.         using difference_type = std::ptrdiff_t;
  107.  
  108.         void fill(const ValueType& value) {
  109.             std::fill(begin(), end(), value);
  110.         }
  111.  
  112.         void swap(array& other) noexcept(array_traits::is_nothrow_swappable_v) {
  113.             std::swap_ranges(begin(), end(), other.begin());
  114.         }
  115.  
  116.         iterator begin() noexcept {
  117.             return array_traits::begin(underlying_array);
  118.         }
  119.  
  120.         constexpr const_iterator begin() const noexcept {
  121.             return array_traits::begin(underlying_array);
  122.         }
  123.  
  124.         iterator end() noexcept {
  125.             return array_traits::end(underlying_array);
  126.         }
  127.  
  128.         constexpr const_iterator end() const noexcept {
  129.             return array_traits::end(underlying_array);
  130.         }
  131.  
  132.         reverse_iterator rbegin() noexcept {
  133.             return reverse_iterator{end()};
  134.         }
  135.  
  136.         constexpr const_reverse_iterator rbegin() const noexcept {
  137.             return const_reverse_iterator{end()};
  138.         }
  139.  
  140.         reverse_iterator rend() noexcept {
  141.             return reverse_iterator{begin()};
  142.         }
  143.  
  144.         constexpr const_reverse_iterator rend() const noexcept {
  145.             return const_reverse_iterator{begin()};
  146.         }
  147.  
  148.         constexpr const_iterator cbegin() const noexcept {
  149.             return begin();
  150.         }
  151.  
  152.         constexpr const_iterator cend() const noexcept {
  153.             return begin();
  154.         }
  155.  
  156.         constexpr const_reverse_iterator crbegin() const noexcept {
  157.             return rbegin();
  158.         }
  159.  
  160.         constexpr const_reverse_iterator crend() const noexcept {
  161.             return rend();
  162.         }
  163.  
  164.         constexpr bool empty() const noexcept {
  165.             return size() == 0;
  166.         }
  167.  
  168.         constexpr size_type size() const noexcept {
  169.             return Size;
  170.         }
  171.  
  172.         constexpr size_type max_size() const noexcept {
  173.             return size();
  174.         }
  175.  
  176.         reference operator[](size_type index) {
  177.             return begin()[index];
  178.         }
  179.  
  180.         constexpr const_reference operator[](size_type index) const {
  181.             return begin()[index];
  182.         }
  183.  
  184.         reference at(size_type index) {
  185.             if(index >= size()) {
  186.                 throw std::out_of_range{"index is out of bounds"};
  187.             }
  188.             return begin()[index];
  189.         }
  190.  
  191.         constexpr const_reference at(size_type index) const {
  192.             if(index >= size()) {
  193.                 throw std::out_of_range{"index is out of bounds"};
  194.             }
  195.             return begin()[index];
  196.         }
  197.  
  198.         reference front() {
  199.             return begin()[0];
  200.         }
  201.  
  202.         constexpr const_reference front() const {
  203.             return begin()[0];
  204.         }
  205.  
  206.         reference back() {
  207.             return begin()[size() - 1];
  208.         }
  209.  
  210.         const_reference back() const {
  211.             return begin()[size() - 1];
  212.         }
  213.  
  214.         ValueType* data() noexcept {
  215.             return begin();
  216.         }
  217.  
  218.         constexpr const ValueType* data() const noexcept {
  219.             return begin();
  220.         }
  221.  
  222.         typename array_traits::type underlying_array;
  223.  
  224.     };
  225.  
  226.     template<typename ValueType, size_t Size>
  227.     bool operator==(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  228.         return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  229.     }
  230.  
  231.     template<typename ValueType, size_t Size>
  232.     bool operator!=(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  233.         return !(lhs == rhs);
  234.     }
  235.  
  236.     template<typename ValueType, size_t Size>
  237.     bool operator<(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  238.         return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  239.     }
  240.  
  241.     template<typename ValueType, size_t Size>
  242.     bool operator>(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  243.         return rhs < lhs;
  244.     }
  245.  
  246.     template<typename ValueType, size_t Size>
  247.     bool operator<=(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  248.         return !(rhs < lhs);
  249.     }
  250.  
  251.     template<typename ValueType, size_t Size>
  252.     bool operator>=(const array<ValueType, Size>& lhs, const array<ValueType, Size>& rhs) {
  253.         return !(lhs < rhs);
  254.     }
  255.  
  256.     template<typename ValueType, size_t Size>
  257.     void swap(array<ValueType, Size>& lhs, array<ValueType, Size>& rhs) noexcept(noexcept(lhs.swap(rhs)));
  258.  
  259.     template<typename>
  260.     struct tuple_size;
  261.  
  262.     template<size_t, typename>
  263.     struct tuple_element;
  264.  
  265.     template<typename ValueType, size_t Size>
  266.     struct tuple_size<array<ValueType, Size>> : std::integral_constant<size_t, Size> { };
  267.  
  268.     template<size_t Index, typename ValueType, size_t Size>
  269.     struct tuple_element<Index, array<ValueType, Size>> {
  270.         static_assert(Index < Size, "invalid index (Index >= Size)");
  271.         using type = ValueType;
  272.     };
  273.  
  274.     template<size_t Index, typename ValueType, size_t Size>
  275.     ValueType& get(array<ValueType, Size>& arr) noexcept {
  276.         static_assert(Index < Size, "invalid index (Index >= Size)");
  277.         return arr[Index];
  278.     }
  279.  
  280.     template<size_t Index, typename ValueType, size_t Size>
  281.     ValueType&& get(array<ValueType, Size>&& arr) noexcept {
  282.         static_assert(Index < Size, "invalid index (Index >= Size)");
  283.         return std::move(arr[Index]);
  284.     }
  285.  
  286.     template<size_t Index, typename ValueType, size_t Size>
  287.     constexpr const ValueType& get(const array<ValueType, Size>& arr) noexcept {
  288.         static_assert(Index < Size, "invalid index (Index >= Size)");
  289.         return arr[Index];
  290.     }
  291.  
  292. }
  293.  
  294. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement