Created
June 8, 2016 02:17
-
-
Save ldionne/9750c497fd73713717dac3d752cf563a to your computer and use it in GitHub Desktop.
Patch to implement P0107 in libc++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 4d6f53adf9ddb41ae6b477a39b8b609159c74cf2 | |
Author: Louis Dionne <ldionne.2@gmail.com> | |
Date: Tue May 24 15:36:02 2016 -0700 | |
[array] Implement P0107 improving the support for constexpr in std::array | |
diff --git a/include/array b/include/array | |
index 719286d..28d093d 100644 | |
--- a/include/array | |
+++ b/include/array | |
@@ -37,18 +37,18 @@ struct array | |
void swap(array& a) noexcept(is_nothrow_swappable_v<T>); | |
// iterators: | |
- iterator begin() noexcept; | |
- const_iterator begin() const noexcept; | |
- iterator end() noexcept; | |
- const_iterator end() const noexcept; | |
+ iterator begin() noexcept; // constexpr in C++17 | |
+ const_iterator begin() const noexcept; // constexpr in C++17 | |
+ iterator end() noexcept; // constexpr in C++17 | |
+ const_iterator end() const noexcept; // constexpr in C++17 | |
reverse_iterator rbegin() noexcept; | |
const_reverse_iterator rbegin() const noexcept; | |
reverse_iterator rend() noexcept; | |
const_reverse_iterator rend() const noexcept; | |
- const_iterator cbegin() const noexcept; | |
- const_iterator cend() const noexcept; | |
+ const_iterator cbegin() const noexcept; // constexpr in C++17 | |
+ const_iterator cend() const noexcept; // constexpr in C++17 | |
const_reverse_iterator crbegin() const noexcept; | |
const_reverse_iterator crend() const noexcept; | |
@@ -58,32 +58,32 @@ struct array | |
constexpr bool empty() const noexcept; | |
// element access: | |
- reference operator[](size_type n); | |
+ reference operator[](size_type n); // constexpr in C++17 | |
const_reference operator[](size_type n) const; // constexpr in C++14 | |
const_reference at(size_type n) const; // constexpr in C++14 | |
- reference at(size_type n); | |
+ reference at(size_type n); // constexpr in C++17 | |
- reference front(); | |
+ reference front(); // constexpr in C++17 | |
const_reference front() const; // constexpr in C++14 | |
- reference back(); | |
+ reference back(); // constexpr in C++17 | |
const_reference back() const; // constexpr in C++14 | |
- T* data() noexcept; | |
- const T* data() const noexcept; | |
+ T* data() noexcept; // constexpr in C++17 | |
+ const T* data() const noexcept; // constexpr in C++17 | |
}; | |
template <class T, size_t N> | |
- bool operator==(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N> | |
- bool operator!=(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator!=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N> | |
- bool operator<(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator<(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N> | |
- bool operator>(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator>(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N> | |
- bool operator<=(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator<=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N> | |
- bool operator>=(const array<T,N>& x, const array<T,N>& y); | |
+ bool operator>=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++17 | |
template <class T, size_t N > | |
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); | |
@@ -152,13 +152,13 @@ struct _LIBCPP_TYPE_VIS_ONLY array | |
{ _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);} | |
// iterators: | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
iterator begin() _NOEXCEPT {return iterator(__elems_);} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);} | |
_LIBCPP_INLINE_VISIBILITY | |
@@ -170,9 +170,9 @@ struct _LIBCPP_TYPE_VIS_ONLY array | |
_LIBCPP_INLINE_VISIBILITY | |
const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
const_iterator cbegin() const _NOEXCEPT {return begin();} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
const_iterator cend() const _NOEXCEPT {return end();} | |
_LIBCPP_INLINE_VISIBILITY | |
const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} | |
@@ -188,23 +188,24 @@ struct _LIBCPP_TYPE_VIS_ONLY array | |
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;} | |
// element access: | |
- _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __elems_[__n];} | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference operator[](size_type __n) {return __elems_[__n];} | |
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference operator[](size_type __n) const {return __elems_[__n];} | |
- reference at(size_type __n); | |
+ _LIBCPP_CONSTEXPR_AFTER_CXX14 reference at(size_type __n); | |
_LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference at(size_type __n) const; | |
- _LIBCPP_INLINE_VISIBILITY reference front() {return __elems_[0];} | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() {return __elems_[0];} | |
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];} | |
- _LIBCPP_INLINE_VISIBILITY reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];} | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];} | |
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size > 0 ? _Size-1 : 0];} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
value_type* data() _NOEXCEPT {return __elems_;} | |
- _LIBCPP_INLINE_VISIBILITY | |
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
const value_type* data() const _NOEXCEPT {return __elems_;} | |
}; | |
template <class _Tp, size_t _Size> | |
+_LIBCPP_CONSTEXPR_AFTER_CXX14 | |
typename array<_Tp, _Size>::reference | |
array<_Tp, _Size>::at(size_type __n) | |
{ | |
@@ -232,15 +233,19 @@ array<_Tp, _Size>::at(size_type __n) const | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
- return _VSTD::equal(__x.__elems_, __x.__elems_ + _Size, __y.__elems_); | |
+ for (typename array<_Tp, _Size>::size_type __i = 0; __i < _Size; ++__i) { | |
+ if (!(__x[__i] == __y[__i])) | |
+ return false; | |
+ } | |
+ return true; | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
@@ -248,15 +253,29 @@ operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
- return _VSTD::lexicographical_compare(__x.__elems_, __x.__elems_ + _Size, __y.__elems_, __y.__elems_ + _Size); | |
+ typedef typename array<_Tp, _Size>::const_iterator _Iterator; | |
+ _Iterator __first1 = __x.begin(); | |
+ _Iterator __last1 = __x.end(); | |
+ | |
+ _Iterator __first2 = __y.begin(); | |
+ _Iterator __last2 = __y.end(); | |
+ | |
+ for (; __first2 != __last2; ++__first1, (void) ++__first2) | |
+ { | |
+ if (__first1 == __last1 || *__first1 < *__first2) | |
+ return true; | |
+ if (*__first2 < *__first1) | |
+ return false; | |
+ } | |
+ return false; | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
@@ -264,7 +283,7 @@ operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
@@ -272,7 +291,7 @@ operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
bool | |
operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
{ | |
@@ -280,7 +299,7 @@ operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) | |
} | |
template <class _Tp, size_t _Size> | |
-inline _LIBCPP_INLINE_VISIBILITY | |
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
typename enable_if | |
< | |
_Size == 0 || | |
diff --git a/test/std/containers/sequences/array/P0107.pass.cpp b/test/std/containers/sequences/array/P0107.pass.cpp | |
new file mode 100644 | |
index 0000000..fb4c326 | |
--- /dev/null | |
+++ b/test/std/containers/sequences/array/P0107.pass.cpp | |
@@ -0,0 +1,86 @@ | |
+//===----------------------------------------------------------------------===// | |
+// | |
+// The LLVM Compiler Infrastructure | |
+// | |
+// This file is dual licensed under the MIT and the University of Illinois Open | |
+// Source Licenses. See LICENSE.TXT for details. | |
+// | |
+//===----------------------------------------------------------------------===// | |
+ | |
+#include <array> | |
+ | |
+ | |
+// Test P0107 (constexpr support for std::array) | |
+// | |
+// We just make sure that the methods modified by P0107 can be called inside | |
+// a constexpr context. | |
+#if _LIBCPP_STD_VER > 14 | |
+template <typename Array> | |
+constexpr bool test() { | |
+ // begin()/end() on a const array | |
+ { | |
+ Array const c{}; | |
+ typename Array::const_iterator it1 = c.begin(); | |
+ typename Array::const_iterator it2 = c.end(); | |
+ } | |
+ | |
+ // begin()/end() on a non-const array | |
+ { | |
+ Array c{}; | |
+ typename Array::iterator it1 = c.begin(); | |
+ typename Array::iterator it2 = c.end(); | |
+ typename Array::const_iterator it3 = c.cbegin(); | |
+ typename Array::const_iterator it4 = c.cend(); | |
+ } | |
+ | |
+ // Other accessors | |
+ { | |
+ Array c{}; | |
+ typename Array::reference i = c.back(); | |
+ typename Array::reference j = c.front(); | |
+ typename Array::reference k = c[0]; | |
+ typename Array::reference l = c.at(0); | |
+ } | |
+ | |
+ // data() on const and non-const array | |
+ { | |
+ Array c{}; | |
+ typename Array::pointer i = c.data(); | |
+ | |
+ Array const c_const{}; | |
+ typename Array::const_pointer j = c_const.data(); | |
+ } | |
+ | |
+ // comparison operators | |
+ { | |
+ Array c1{}, c2{}; | |
+ (void)(c1 == c2); | |
+ (void)(c1 != c2); | |
+ (void)(c1 < c2); | |
+ (void)(c1 <= c2); | |
+ (void)(c1 > c2); | |
+ (void)(c1 >= c2); | |
+ } | |
+ | |
+ return true; | |
+} | |
+ | |
+static_assert(test<std::array<int, 1>>(), ""); | |
+static_assert(test<std::array<int, 2>>(), ""); | |
+static_assert(test<std::array<int, 3>>(), ""); | |
+static_assert(test<std::array<int, 4>>(), ""); | |
+ | |
+static_assert(test<std::array<char, 1>>(), ""); | |
+static_assert(test<std::array<char, 2>>(), ""); | |
+static_assert(test<std::array<char, 3>>(), ""); | |
+static_assert(test<std::array<char, 4>>(), ""); | |
+ | |
+static_assert(test<std::array<float, 1>>(), ""); | |
+static_assert(test<std::array<float, 2>>(), ""); | |
+static_assert(test<std::array<float, 3>>(), ""); | |
+static_assert(test<std::array<float, 4>>(), ""); | |
+#endif | |
+ | |
+int main() { | |
+ | |
+} | |
diff --git a/test/std/containers/sequences/array/at.pass.cpp b/test/std/containers/sequences/array/at.pass.cpp | |
index 5cb89df..0f9ecbc 100644 | |
--- a/test/std/containers/sequences/array/at.pass.cpp | |
+++ b/test/std/containers/sequences/array/at.pass.cpp | |
@@ -10,9 +10,9 @@ | |
// XFAIL: libcpp-no-exceptions | |
// <array> | |
-// reference operator[] (size_type) | |
+// reference operator[] (size_type) // constexpr in C++17 | |
// const_reference operator[] (size_type); // constexpr in C++14 | |
-// reference at (size_type) | |
+// reference at (size_type) // constexpr in C++17 | |
// const_reference at (size_type); // constexpr in C++14 | |
#include <array> | |
diff --git a/test/std/containers/sequences/array/front_back.pass.cpp b/test/std/containers/sequences/array/front_back.pass.cpp | |
index bccaade..78c5812 100644 | |
--- a/test/std/containers/sequences/array/front_back.pass.cpp | |
+++ b/test/std/containers/sequences/array/front_back.pass.cpp | |
@@ -9,8 +9,8 @@ | |
// <array> | |
-// reference front(); | |
-// reference back(); | |
+// reference front(); // constexpr in C++17 | |
+// reference back(); // constexpr in C++17 | |
// const_reference front(); // constexpr in C++14 | |
// const_reference back(); // constexpr in C++14 | |
diff --git a/test/std/containers/sequences/array/indexing.pass.cpp b/test/std/containers/sequences/array/indexing.pass.cpp | |
index 5ccb0b4..dc63238 100644 | |
--- a/test/std/containers/sequences/array/indexing.pass.cpp | |
+++ b/test/std/containers/sequences/array/indexing.pass.cpp | |
@@ -9,9 +9,9 @@ | |
// <array> | |
-// reference operator[] (size_type) | |
+// reference operator[] (size_type) // constexpr in C++17 | |
// const_reference operator[] (size_type); // constexpr in C++14 | |
-// reference at (size_type) | |
+// reference at (size_type) // constexpr in C++17 | |
// const_reference at (size_type); // constexpr in C++14 | |
#include <array> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment