libstdc++
array
Go to the documentation of this file.
00001 // Debugging array implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2012-2016 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(__is_nothrow_swappable<_Tp>::value)
00090       { std::swap_ranges(begin(), end(), __other.begin()); }
00091 
00092       // Iterators.
00093       iterator
00094       begin() noexcept
00095       { return iterator(data()); }
00096 
00097       const_iterator
00098       begin() const noexcept
00099       { return const_iterator(data()); }
00100 
00101       iterator
00102       end() noexcept
00103       { return iterator(data() + _Nm); }
00104 
00105       const_iterator
00106       end() const noexcept
00107       { return const_iterator(data() + _Nm); }
00108 
00109       reverse_iterator 
00110       rbegin() noexcept
00111       { return reverse_iterator(end()); }
00112 
00113       const_reverse_iterator 
00114       rbegin() const noexcept
00115       { return const_reverse_iterator(end()); }
00116 
00117       reverse_iterator 
00118       rend() noexcept
00119       { return reverse_iterator(begin()); }
00120 
00121       const_reverse_iterator 
00122       rend() const noexcept
00123       { return const_reverse_iterator(begin()); }
00124 
00125       const_iterator
00126       cbegin() const noexcept
00127       { return const_iterator(data()); }
00128 
00129       const_iterator
00130       cend() const noexcept
00131       { return const_iterator(data() + _Nm); }
00132 
00133       const_reverse_iterator 
00134       crbegin() const noexcept
00135       { return const_reverse_iterator(end()); }
00136 
00137       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       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       reference
00168       at(size_type __n)
00169       {
00170         if (__n >= _Nm)
00171           std::__throw_out_of_range_fmt(__N("array::at: __n "
00172                                             "(which is %zu) >= _Nm "
00173                                             "(which is %zu)"),
00174                                         __n, _Nm);
00175         return _AT_Type::_S_ref(_M_elems, __n);
00176       }
00177 
00178       constexpr const_reference
00179       at(size_type __n) const
00180       {
00181         // Result of conditional expression must be an lvalue so use
00182         // boolean ? lvalue : (throw-expr, lvalue)
00183         return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
00184           : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
00185                                                ">= _Nm (which is %zu)"),
00186                                            __n, _Nm),
00187              _AT_Type::_S_ref(_M_elems, 0));
00188       }
00189 
00190       reference 
00191       front() noexcept
00192       {
00193         __glibcxx_check_nonempty();
00194         return *begin();
00195       }
00196 
00197       constexpr const_reference 
00198       front() const noexcept
00199       {
00200         return _Nm ? _AT_Type::_S_ref(_M_elems, 0)
00201           : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
00202              _AT_Type::_S_ref(_M_elems, 0));
00203       }
00204 
00205       reference 
00206       back() noexcept
00207       {
00208         __glibcxx_check_nonempty();
00209         return _Nm ? *(end() - 1) : *end();
00210       }
00211 
00212       constexpr const_reference 
00213       back() const noexcept
00214       {
00215         return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
00216           : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
00217              _AT_Type::_S_ref(_M_elems, 0));
00218       }
00219 
00220       pointer
00221       data() noexcept
00222       { return _AT_Type::_S_ptr(_M_elems); }
00223 
00224       const_pointer
00225       data() const noexcept
00226       { return _AT_Type::_S_ptr(_M_elems); }
00227     };
00228 
00229   // Array comparisons.
00230   template<typename _Tp, std::size_t _Nm>
00231     inline bool 
00232     operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00233     { return std::equal(__one.begin(), __one.end(), __two.begin()); }
00234 
00235   template<typename _Tp, std::size_t _Nm>
00236     inline bool
00237     operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00238     { return !(__one == __two); }
00239 
00240   template<typename _Tp, std::size_t _Nm>
00241     inline bool
00242     operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
00243     { 
00244       return std::lexicographical_compare(__a.begin(), __a.end(),
00245                                           __b.begin(), __b.end()); 
00246     }
00247 
00248   template<typename _Tp, std::size_t _Nm>
00249     inline bool
00250     operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00251     { return __two < __one; }
00252 
00253   template<typename _Tp, std::size_t _Nm>
00254     inline bool
00255     operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00256     { return !(__one > __two); }
00257 
00258   template<typename _Tp, std::size_t _Nm>
00259     inline bool
00260     operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
00261     { return !(__one < __two); }
00262 
00263   // Specialized algorithms.
00264   template<typename _Tp, std::size_t _Nm>
00265     inline void
00266     swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
00267     noexcept(noexcept(__one.swap(__two)))
00268     { __one.swap(__two); }
00269 
00270   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00271     constexpr _Tp&
00272     get(array<_Tp, _Nm>& __arr) noexcept
00273     {
00274       static_assert(_Int < _Nm, "index is out of bounds");
00275       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
00276         _S_ref(__arr._M_elems, _Int);
00277     }
00278 
00279   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00280     constexpr _Tp&&
00281     get(array<_Tp, _Nm>&& __arr) noexcept
00282     {
00283       static_assert(_Int < _Nm, "index is out of bounds");
00284       return std::move(__debug::get<_Int>(__arr));
00285     }
00286 
00287   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00288     constexpr const _Tp&
00289     get(const array<_Tp, _Nm>& __arr) noexcept
00290     {
00291       static_assert(_Int < _Nm, "index is out of bounds");
00292       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
00293         _S_ref(__arr._M_elems, _Int);
00294     }
00295 } // namespace __debug
00296 
00297 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00298   // Tuple interface to class template array.
00299 
00300   /// tuple_size
00301   template<typename _Tp, std::size_t _Nm>
00302     struct tuple_size<std::__debug::array<_Tp, _Nm>>
00303     : public integral_constant<std::size_t, _Nm> { };
00304 
00305   /// tuple_element
00306   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
00307     struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>>
00308     {
00309       static_assert(_Int < _Nm, "index is out of bounds");
00310       typedef _Tp type;
00311     };
00312 
00313   template<typename _Tp, std::size_t _Nm>
00314     struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type
00315     { };
00316 
00317 _GLIBCXX_END_NAMESPACE_VERSION
00318 } // namespace std
00319 
00320 #endif // _GLIBCXX_DEBUG_ARRAY