diff mbox

[libstdc++] PR libstdc++/64656

Message ID 20150119143716.GG3360@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Jan. 19, 2015, 2:37 p.m. UTC
On 19/01/15 02:48 +0200, Ville Voutilainen wrote:
>Minor additions:
>- add a comment to the #endif for the c++14 #if
>- fix the doc comments to talk about reverse iterators

Thanks, I like the new comments more.

>This passes the testsuite.

Posted during stage3 so OK for trunk.

>diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
>index fa18aa2..a5a511c 100644
>--- a/libstdc++-v3/include/bits/range_access.h
>+++ b/libstdc++-v3/include/bits/range_access.h
>@@ -33,7 +33,7 @@
> #pragma GCC system_header
>
> #if __cplusplus >= 201103L
>-
>+#include <initializer_list>
> namespace std _GLIBCXX_VISIBILITY(default)
> {
> _GLIBCXX_BEGIN_NAMESPACE_VERSION
>@@ -97,6 +97,131 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>     end(_Tp (&__arr)[_Nm])
>     { return __arr + _Nm; }
>
>+#if __cplusplus >= 201402L
>+  /**
>+   *  @brief  Return an iterator pointing to the first element of
>+   *          the const container.
>+   *  @param  __cont  Container.
>+   */
>+  template<class _Container>
>+    inline constexpr auto

The 'inline' is redundant with 'constexpr' but harmless.

I notice we are missing the 'constexpr' that C++14 adds to the
existing begin/end functions for arrays, so I'm committing this
slightly changed version. I added _GLIBCXX14_CONSTEXPR to the
existing begin() and end() functions for arrays, and changed the new
test to use VERIFY instead of assert and to use the functions in
constant expressions.

Tested x86_64-linux and committed to trunk.
diff mbox

Patch

commit a19707d5d6ed6f93ea8ac613f6a1f35c0c996f90
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jan 19 13:42:32 2015 +0000

    2015-01-19  Ville Voutilainen  <ville.voutilainen@gmail.com>
    	    Jonathan Wakely  <jwakely@redhat.com>
    
    	* include/bits/range_access.h (begin, end): Use _GLIBCXX14_CONSTEXPR
    	on overloads for arrays.
    	(cbegin, cend, rbegin, rend, crbegin, crend): New.
    	* testsuite/24_iterators/range_access_cpp14.cc: New.

diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index fa18aa2..510c0b1 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -33,7 +33,7 @@ 
 #pragma GCC system_header
 
 #if __cplusplus >= 201103L
-
+#include <initializer_list>
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -83,7 +83,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  @param  __arr  Array.
    */
   template<class _Tp, size_t _Nm>
-    inline _Tp*
+    inline _GLIBCXX14_CONSTEXPR _Tp*
     begin(_Tp (&__arr)[_Nm])
     { return __arr; }
 
@@ -93,10 +93,135 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  @param  __arr  Array.
    */
   template<class _Tp, size_t _Nm>
-    inline _Tp*
+    inline _GLIBCXX14_CONSTEXPR _Tp*
     end(_Tp (&__arr)[_Nm])
     { return __arr + _Nm; }
 
+#if __cplusplus >= 201402L
+  /**
+   *  @brief  Return an iterator pointing to the first element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline constexpr auto
+    cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
+      -> decltype(std::begin(__cont))
+    { return std::begin(__cont); }
+
+  /**
+   *  @brief  Return an iterator pointing to one past the last element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline constexpr auto
+    cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
+      -> decltype(std::end(__cont))
+    { return std::end(__cont); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing to the last element of
+   *          the container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    rbegin(_Container& __cont) -> decltype(__cont.rbegin())
+    { return __cont.rbegin(); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing to the last element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    rbegin(const _Container& __cont) -> decltype(__cont.rbegin())
+    { return __cont.rbegin(); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing one past the first element of
+   *          the container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    rend(_Container& __cont) -> decltype(__cont.rend())
+    { return __cont.rend(); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing one past the first element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    rend(const _Container& __cont) -> decltype(__cont.rend())
+    { return __cont.rend(); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing to the last element of
+   *          the array.
+   *  @param  __arr  Array.
+   */
+  template<class _Tp, size_t _Nm>
+    inline reverse_iterator<_Tp*>
+    rbegin(_Tp (&__arr)[_Nm])
+    { return reverse_iterator<_Tp*>(__arr + _Nm); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing one past the first element of
+   *          the array.
+   *  @param  __arr  Array.
+   */
+  template<class _Tp, size_t _Nm>
+    inline reverse_iterator<_Tp*>
+    rend(_Tp (&__arr)[_Nm])
+    { return reverse_iterator<_Tp*>(__arr); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing to the last element of
+   *          the initializer_list.
+   *  @param  __il  initializer_list.
+   */
+  template<class _Tp>
+    inline reverse_iterator<const _Tp*>
+    rbegin(initializer_list<_Tp> __il)
+    { return reverse_iterator<const _Tp*>(__il.end()); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing one past the first element of
+   *          the initializer_list.
+   *  @param  __il  initializer_list.
+   */
+  template<class _Tp>
+    inline reverse_iterator<const _Tp*>
+    rend(initializer_list<_Tp> __il)
+    { return reverse_iterator<const _Tp*>(__il.begin()); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing to the last element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont))
+    { return std::rbegin(__cont); }
+
+  /**
+   *  @brief  Return a reverse iterator pointing one past the first element of
+   *          the const container.
+   *  @param  __cont  Container.
+   */
+  template<class _Container>
+    inline auto
+    crend(const _Container& __cont) -> decltype(std::rend(__cont))
+    { return std::rend(__cont); }
+
+#endif // C++14
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc b/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc
new file mode 100644
index 0000000..a75e04c
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc
@@ -0,0 +1,82 @@ 
+// { dg-do run }
+// { dg-options "-std=gnu++14" }
+
+// 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.6.5, range access [iterator.range]
+
+#include <iterator>
+#include <vector>
+#include <testsuite_hooks.h>
+
+bool test __attribute__((unused)) = true;
+
+void
+test01()
+{
+  int i[1];
+  VERIFY(std::cbegin(i) == i);
+  VERIFY(std::cend(i) == i+1);
+  VERIFY(std::rbegin(i) == std::reverse_iterator<int*>(i+1));
+  VERIFY(std::rend(i) == std::reverse_iterator<int*>(i));
+  VERIFY(std::crbegin(i) == std::reverse_iterator<int*>(i+1));
+  VERIFY(std::crend(i) == std::reverse_iterator<int*>(i));
+}
+
+void
+test02()
+{
+  static int i[1];
+  constexpr auto b  __attribute__((unused)) = std::begin(i);
+  constexpr auto e  __attribute__((unused)) = std::end(i);
+  constexpr auto cb __attribute__((unused)) = std::cbegin(i);
+  constexpr auto ce __attribute__((unused)) = std::cend(i);
+}
+
+int
+test03()
+{
+  std::initializer_list<int> il{1};
+  VERIFY(std::cbegin(il) == il.begin());
+  VERIFY(std::cend(il) == il.end());
+  VERIFY(std::rbegin(il) == std::reverse_iterator<const int*>(il.end()));
+  VERIFY(std::rend(il) == std::reverse_iterator<const int*>(il.begin()));
+  VERIFY(std::crbegin(il) == std::reverse_iterator<const int*>(il.end()));
+  VERIFY(std::crend(il) == std::reverse_iterator<const int*>(il.begin()));
+}
+
+int
+test04()
+{
+  std::vector<int> v{1};
+  VERIFY(std::cbegin(v) == v.cbegin());
+  VERIFY(std::cend(v) == v.cend());
+  VERIFY(std::rbegin(v) == v.rbegin());
+  VERIFY(std::rend(v) == v.rend());
+  VERIFY(std::crbegin(v) == v.crbegin());
+  VERIFY(std::crend(v) == v.crend());
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}