[v3 PATCH] Implement N4280, Non-member size() and more (Revision 2)

Ville Voutilainen ville.voutilainen@gmail.com
Wed Jul 15 00:05:00 GMT 2015


Tested on Linux-PPC64.

2015-07-15  Ville Voutilainen  <ville.voutilainen@gmail.com>
    Implement N4280, Non-member size() and more (Revision 2)
    * include/bits/range_access.h: Change class to typename
    in every template.
    * include/bits/range_access.h(size, empty, data): New.
    * testsuite/24_iterators/container_access.cc: New.
-------------- next part --------------
diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index 510c0b1..448462f 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -43,7 +43,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     begin(_Container& __cont) -> decltype(__cont.begin())
     { return __cont.begin(); }
@@ -53,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     begin(const _Container& __cont) -> decltype(__cont.begin())
     { return __cont.begin(); }
@@ -63,7 +63,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     end(_Container& __cont) -> decltype(__cont.end())
     { return __cont.end(); }
@@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     end(const _Container& __cont) -> decltype(__cont.end())
     { return __cont.end(); }
@@ -82,7 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  @brief  Return an iterator pointing to the first element of the array.
    *  @param  __arr  Array.
    */
-  template<class _Tp, size_t _Nm>
+  template<typename _Tp, size_t _Nm>
     inline _GLIBCXX14_CONSTEXPR _Tp*
     begin(_Tp (&__arr)[_Nm])
     { return __arr; }
@@ -92,7 +92,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          of the array.
    *  @param  __arr  Array.
    */
-  template<class _Tp, size_t _Nm>
+  template<typename _Tp, size_t _Nm>
     inline _GLIBCXX14_CONSTEXPR _Tp*
     end(_Tp (&__arr)[_Nm])
     { return __arr + _Nm; }
@@ -103,7 +103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline constexpr auto
     cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
       -> decltype(std::begin(__cont))
@@ -114,7 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline constexpr auto
     cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
       -> decltype(std::end(__cont))
@@ -125,7 +125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     rbegin(_Container& __cont) -> decltype(__cont.rbegin())
     { return __cont.rbegin(); }
@@ -135,7 +135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     rbegin(const _Container& __cont) -> decltype(__cont.rbegin())
     { return __cont.rbegin(); }
@@ -145,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     rend(_Container& __cont) -> decltype(__cont.rend())
     { return __cont.rend(); }
@@ -155,7 +155,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     rend(const _Container& __cont) -> decltype(__cont.rend())
     { return __cont.rend(); }
@@ -165,7 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the array.
    *  @param  __arr  Array.
    */
-  template<class _Tp, size_t _Nm>
+  template<typename _Tp, size_t _Nm>
     inline reverse_iterator<_Tp*>
     rbegin(_Tp (&__arr)[_Nm])
     { return reverse_iterator<_Tp*>(__arr + _Nm); }
@@ -175,7 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the array.
    *  @param  __arr  Array.
    */
-  template<class _Tp, size_t _Nm>
+  template<typename _Tp, size_t _Nm>
     inline reverse_iterator<_Tp*>
     rend(_Tp (&__arr)[_Nm])
     { return reverse_iterator<_Tp*>(__arr); }
@@ -185,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the initializer_list.
    *  @param  __il  initializer_list.
    */
-  template<class _Tp>
+  template<typename _Tp>
     inline reverse_iterator<const _Tp*>
     rbegin(initializer_list<_Tp> __il)
     { return reverse_iterator<const _Tp*>(__il.end()); }
@@ -195,7 +195,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the initializer_list.
    *  @param  __il  initializer_list.
    */
-  template<class _Tp>
+  template<typename _Tp>
     inline reverse_iterator<const _Tp*>
     rend(initializer_list<_Tp> __il)
     { return reverse_iterator<const _Tp*>(__il.begin()); }
@@ -205,7 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont))
     { return std::rbegin(__cont); }
@@ -215,13 +215,90 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *          the const container.
    *  @param  __cont  Container.
    */
-  template<class _Container>
+  template<typename _Container>
     inline auto
     crend(const _Container& __cont) -> decltype(std::rend(__cont))
     { return std::rend(__cont); }
 
 #endif // C++14
 
+#if __cplusplus > 201402L
+
+  /**
+   *  @brief  Return the size of a container.
+   *  @param  __cont  Container.
+   */
+  template <typename _Container>
+    constexpr auto
+    size(const _Container& __cont) -> decltype(__cont.size())
+    { return __cont.size(); }
+
+  /**
+   *  @brief  Return the size of an array.
+   *  @param  __array  Array.
+   */
+  template <typename _Tp, size_t _N>
+  constexpr size_t size(const _Tp (&/*__array*/)[_N]) noexcept
+    { return _N; }
+
+  /**
+   *  @brief  Return whether a container is empty.
+   *  @param  __cont  Container.
+   */
+  template <typename _Container>
+  constexpr auto empty(const _Container& __cont) -> decltype(__cont.empty())
+    { return __cont.empty(); }
+
+  /**
+   *  @brief  Return whether an array is empty (always false).
+   *  @param  __array  Container.
+   */
+  template <typename _Tp, size_t _N>
+  constexpr bool empty(const _Tp (&/*__array*/)[_N]) noexcept
+    { return false; }
+
+  /**
+   *  @brief  Return whether an initializer_list is empty.
+   *  @param  __il  Initializer list.
+   */
+  template <typename _Tp>
+  constexpr bool empty(initializer_list<_Tp> __il) noexcept
+    { return __il.size() == 0;}
+
+  /**
+   *  @brief  Return the data pointer of a container.
+   *  @param  __cont  Container.
+   */
+  template <typename _Container>
+  constexpr auto data(_Container& __cont) -> decltype(__cont.data())
+    { return __cont.data(); }
+
+  /**
+   *  @brief  Return the data pointer of a const container.
+   *  @param  __cont  Container.
+   */
+  template <typename _Container>
+  constexpr auto data(const _Container& __cont) -> decltype(__cont.data())
+    { return __cont.data(); }
+
+  /**
+   *  @brief  Return the data pointer of an array.
+   *  @param  __array  Array.
+   */
+  template <typename _Tp, size_t _N>
+  constexpr _Tp* data(_Tp (&__array)[_N]) noexcept
+    { return __array; }
+
+  /**
+   *  @brief  Return the data pointer of an initializer list.
+   *  @param  __il  Initializer list.
+   */
+  template <typename _Tp>
+  constexpr const _Tp* data(initializer_list<_Tp> __il) noexcept
+    { return __il.begin(); }
+
+#endif // C++17
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/24_iterators/container_access.cc b/libstdc++-v3/testsuite/24_iterators/container_access.cc
new file mode 100644
index 0000000..0cbecde
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/container_access.cc
@@ -0,0 +1,89 @@
+// { dg-do run }
+// { dg-options "-std=gnu++17" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 24.8, container access [iterator.container]
+
+#include <iterator>
+#include <vector>
+#include <testsuite_hooks.h>
+
+bool test __attribute__((unused)) = true;
+
+void
+test01()
+{
+  int i[42];
+  VERIFY(std::data(i) == i);
+  VERIFY(std::size(i) == 42);
+  VERIFY(!std::empty(i));
+}
+
+void
+test02()
+{
+  static constexpr int i[42]{};
+  constexpr auto d = std::data(i);
+  static_assert(d == i);
+  constexpr auto s = std::size(i);
+  static_assert(s == 42);
+  constexpr auto e = std::empty(i);
+  static_assert(!e);
+}
+
+int
+test03()
+{
+  std::initializer_list<int> il{1,2,3};
+  VERIFY(std::data(il) == il.begin());
+  VERIFY(std::size(il) == 3);
+  VERIFY(!std::empty(il));
+  std::initializer_list<int> il2{};
+  VERIFY(std::size(il2) == 0);
+  VERIFY(std::empty(il2));
+  constexpr std::initializer_list<int> il3{1,2,3};
+  constexpr auto d = std::data(il3);
+  static_assert(d == il3.begin());
+  constexpr auto s = std::size(il3);
+  static_assert(s == 3);
+  constexpr auto e = std::empty(il3);
+  static_assert(!e);
+
+}
+
+int
+test04()
+{
+  std::vector<int> v{1,2,3};
+  VERIFY(std::data(v) == v.data());
+  VERIFY(std::size(v) == v.size());
+  VERIFY(!std::empty(v));
+  std::vector<int> v2{};
+  VERIFY(std::size(v2) == v2.size());
+  VERIFY(std::empty(v2));
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}


More information about the Gcc-patches mailing list