This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [PATCH, libstdc++] PR libstdc++/64656
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: Ville Voutilainen <ville dot voutilainen at gmail dot com>
- Cc: libstdc++ at gcc dot gnu dot org, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 19 Jan 2015 14:37:16 +0000
- Subject: Re: [PATCH, libstdc++] PR libstdc++/64656
- Authentication-results: sourceware.org; auth=none
- References: <CAFk2RUYLe5FJJqKAyu_1Q2ZAAcjN2ZoQhkQZLExckV6RTQg2Sg at mail dot gmail dot com> <CAFk2RUa_DQprfHyXLLL+2mdaACeKf1yjW3_nkL8uhDQ6W8z4cQ at mail dot gmail dot com>
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.
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();
+}