libstdc++
array
Go to the documentation of this file.
00001 // Debugging array implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2012-2018 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file debug/array
00026  *  This is a Standard C++ Library header.
00027  */
00028 
00029 #ifndef _GLIBCXX_DEBUG_ARRAY
00030 #define _GLIBCXX_DEBUG_ARRAY 1
00031 
00032 #pragma GCC system_header
00033 
00034 #include <array>
00035 
00036 #include <debug/formatter.h>
00037 #include <debug/macros.h>
00038 
00039 namespace std _GLIBCXX_VISIBILITY(default)
00040 {
00041 namespace __debug
00042 {
00043   template<typename _Tp, std::size_t _Nm>
00044     struct array
00045     {
00046       typedef _Tp                                     value_type;
00047       typedef value_type*                             pointer;
00048       typedef const value_type*                       const_pointer;
00049       typedef value_type&                             reference;
00050       typedef const value_type&                       const_reference;
00051       typedef value_type*                             iterator;
00052       typedef const value_type*                       const_iterator;
00053       typedef std::size_t                             size_type;
00054       typedef std::ptrdiff_t                          difference_type;
00055       typedef std::reverse_iterator<iterator>         reverse_iterator;
00056       typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
00057 
00058       // Support for zero-sized arrays mandatory.
00059       typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
00060       typename _AT_Type::_Type                         _M_elems;
00061 
00062       template<std::size_t _Size>
00063         struct _Array_check_subscript
00064         {
00065           std::size_t size() { return _Size; }
00066 
00067           _Array_check_subscript(std::size_t __index)
00068           { __glibcxx_check_subscript(__index); }
00069         };
00070 
00071       template<std::size_t _Size>
00072         struct _Array_check_nonempty
00073         {
00074           bool empty() { return _Size == 0; }
00075 
00076           _Array_check_nonempty()
00077           { __glibcxx_check_nonempty(); }
00078         };
00079 
00080       // No explicit construct/copy/destroy for aggregate type.
00081 
00082       // DR 776.
00083       void
00084       fill(const value_type& __u)
00085       { std::fill_n(begin(), size(), __u); }
00086 
00087       void
00088       swap(array& __other)
00089       noexcept(_AT_Type::_Is_nothrow_swappable::value)
00090       { std::swap_ranges(begin(), end(), __other.begin()); }
00091 
00092       // Iterators.
00093       _GLIBCXX17_CONSTEXPR iterator
00094       begin() noexcept
00095       { return iterator(data()); }
00096 
00097       _GLIBCXX17_CONSTEXPR const_iterator
00098       begin() const noexcept
00099       { return const_iterator(data()); }
00100 
00101       _GLIBCXX17_CONSTEXPR iterator
00102       end() noexcept
00103       { return iterator(data() + _Nm); }
00104 
00105       _GLIBCXX17_CONSTEXPR const_iterator
00106       end() const noexcept
00107       { return const_iterator(data() + _Nm); }
00108 
00109       _GLIBCXX17_CONSTEXPR reverse_iterator
00110       rbegin() noexcept
00111       { return reverse_iterator(end()); }
00112 
00113       _GLIBCXX17_CONSTEXPR const_reverse_iterator
00114       rbegin() const noexcept
00115       { return const_reverse_iterator(end()); }
00116 
00117       _GLIBCXX17_CONSTEXPR reverse_iterator
00118       rend() noexcept
00119       { return reverse_iterator(begin()); }
00120 
00121       _GLIBCXX17_CONSTEXPR const_reverse_iterator
00122       rend() const noexcept
00123       { return const_reverse_iterator(begin()); }
00124 
00125       _GLIBCXX17_CONSTEXPR const_iterator
00126       cbegin() const noexcept
00127       { return const_iterator(data()); }
00128 
00129       _GLIBCXX17_CONSTEXPR const_iterator
00130       cend() const noexcept
00131       { return const_iterator(data() + _Nm); }
00132 
00133       _GLIBCXX17_CONSTEXPR const_reverse_iterator
00134       crbegin() const noexcept
00135       { return const_reverse_iterator(end()); }
00136 
00137       _GLIBCXX17_CONSTEXPR const_reverse_iterator
00138       crend() const noexcept
00139       { return const_reverse_iterator(begin()); }
00140 
00141       // Capacity.
00142       constexpr size_type
00143       size() const noexcept { return _Nm; }
00144 
00145       constexpr size_type
00146       max_size() const noexcept { return _Nm; }
00147 
00148       constexpr bool
00149       empty() const noexcept { return size() == 0; }
00150 
00151       // Element access.
00152       _GLIBCXX17_CONSTEXPR reference
00153       operator[](size_type __n) noexcept
00154       {
00155         __glibcxx_check_subscript(__n);
00156         return _AT_Type::_S_ref(_M_elems, __n);
00157       }
00158 
00159       constexpr const_reference
00160       operator[](size_type __n) const noexcept
00161       {
00162         return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
00163          : (_GLIBCXX_THROW_OR_ABORT(_Array_check_subscript<_Nm>(__n)),
00164             _AT_Type::_S_ref(_M_elems, 0));
00165       }
00166 
00167       _GLIBCXX17_CONSTEXPR reference
00168       at(size_type __n)
00169       {
00170         if (__n >= _Nm)
00171           std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
00172                                             ">= _Nm (which is %zu)"),
00173                                         __n, _Nm);
00174         return _AT_Type::_S_ref(_M_elems, __n);
00175       }
00176 
00177       constexpr const_reference
00178       at(size_type __n) const
00179       {
00180         // Result of conditional expression must be an lvalue so use
00181         // boolean ? lvalue : (throw-expr, lvalue)
00182         return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
00183           : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
00184                                                ">= _Nm (which is %zu)"),
00185                                            __n, _Nm),
00186              _AT_Type::_S_ref(_M_elems, 0));
00187       }
00188 
00189       _GLIBCXX17_CONSTEXPR reference
00190       front() noexcept
00191       {
00192         __glibcxx_check_nonempty();
00193         return *begin();
00194       }
00195 
00196       constexpr const_reference
00197       front() const noexcept
00198       {
00199         return _Nm ? _AT_Type::_S_ref(_M_elems, 0)
00200           : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
00201              _AT_Type::_S_ref(_M_elems, 0));
00202       }
00203 
00204       _GLIBCXX17_CONSTEXPR reference
00205       back() noexcept
00206       {
00207         __glibcxx_check_nonempty();
00208         return _Nm ? *(end() - 1) : *end();
00209       }
00210 
00211       constexpr const_reference
00212       back() const noexcept
00213       {
00214         return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
00215           : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
00216              _AT_Type::_S_ref(_M_elems, 0));
00217       }
00218 
00219       _GLIBCXX17_CONSTEXPR pointer
00220       data() noexcept
00221       { return _AT_Type::_S_ptr(_M_elems); }
00222 
00223       _GLIBCXX17_CONSTEXPR const_pointer
00224       data() const noexcept
00225       { return _AT_Type::_S_ptr(_M_elems); }
00226     };
00227 
00228 #if __cpp_deduction_guides >= 201606
00229   template<typename _Tp, typename... _Up>
00230     array(_Tp, _Up...)
00231       -> array<std::enable_if_t<(std::is_same_v<_Tp, _Up> && ...), _Tp>,
00232                1 + sizeof...(_Up)>;
00233 #endif
00234 
00235   // Array comparisons.
00236   template<typename _Tp, std::size_t _Nm>
00237     inline bool
00238     operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00239     { return std::equal(__one.begin(), __one.end(), __two.begin()); }
00240 
00241   template<typename _Tp, std::size_t _Nm>
00242     inline bool
00243     operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00244     { return !(__one == __two); }
00245 
00246   template<typename _Tp, std::size_t _Nm>
00247     inline bool
00248     operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
00249     {
00250       return std::lexicographical_compare(__a.begin(), __a.end(),
00251                                           __b.begin(), __b.end());
00252     }
00253 
00254   template<typename _Tp, std::size_t _Nm>
00255     inline bool
00256     operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00257     { return __two < __one; }
00258 
00259   template<typename _Tp, std::size_t _Nm>
00260     inline bool
00261     operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00262     { return !(__one > __two); }
00263 
00264   template<typename _Tp, std::size_t _Nm>
00265     inline bool
00266     operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00267     { return !(__one < __two); }
00268 
00269   // Specialized algorithms.
00270 
00271 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
00272   template<typename _Tp, size_t _Nm>
00273     typename enable_if<
00274       !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
00275     swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
00276 #endif
00277 
00278   template<typename _Tp, std::size_t _Nm>
00279     inline void
00280     swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
00281     noexcept(noexcept(__one.swap(__two)))
00282     { __one.swap(__two); }
00283 
00284   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00285     constexpr _Tp&
00286     get(array<_Tp, _Nm>& __arr) noexcept
00287     {
00288       static_assert(_Int < _Nm, "index is out of bounds");
00289       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
00290         _S_ref(__arr._M_elems, _Int);
00291     }
00292 
00293   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00294     constexpr _Tp&&
00295     get(array<_Tp, _Nm>&& __arr) noexcept
00296     {
00297       static_assert(_Int < _Nm, "index is out of bounds");
00298       return std::move(__debug::get<_Int>(__arr));
00299     }
00300 
00301   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00302     constexpr const _Tp&
00303     get(const array<_Tp, _Nm>& __arr) noexcept
00304     {
00305       static_assert(_Int < _Nm, "index is out of bounds");
00306       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
00307         _S_ref(__arr._M_elems, _Int);
00308     }
00309 
00310   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00311     constexpr const _Tp&&
00312     get(const array<_Tp, _Nm>&& __arr) noexcept
00313     {
00314       static_assert(_Int < _Nm, "index is out of bounds");
00315       return std::move(__debug::get<_Int>(__arr));
00316     }
00317 } // namespace __debug
00318 
00319 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00320   // Tuple interface to class template array.
00321 
00322   /// tuple_size
00323   template<typename _Tp, std::size_t _Nm>
00324     struct tuple_size<std::__debug::array<_Tp, _Nm>>
00325     : public integral_constant<std::size_t, _Nm> { };
00326 
00327   /// tuple_element
00328   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00329     struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>>
00330     {
00331       static_assert(_Int < _Nm, "index is out of bounds");
00332       typedef _Tp type;
00333     };
00334 
00335   template<typename _Tp, std::size_t _Nm>
00336     struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type
00337     { };
00338 
00339 _GLIBCXX_END_NAMESPACE_VERSION
00340 } // namespace std
00341 
00342 #endif // _GLIBCXX_DEBUG_ARRAY