Skip to content

Instantly share code, notes, and snippets.

@ldionne
Created June 8, 2016 02:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ldionne/9750c497fd73713717dac3d752cf563a to your computer and use it in GitHub Desktop.
Save ldionne/9750c497fd73713717dac3d752cf563a to your computer and use it in GitHub Desktop.
Patch to implement P0107 in libc++
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