[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