// copy
template <class _Iter>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
_Iter
__unwrap_iter(_Iter __i)
{
}
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
#if _LIBCPP_DEBUG_LEVEL < 2
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
}
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
#else
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
// move
+// __move_constexpr exists so that __move doesn't call itself when delegating to the constexpr
+// version of __move.
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_OutputIterator
-__move(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+__move_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
for (; __first != __last; ++__first, (void) ++__result)
*__result = _VSTD::move(*__first);
return __result;
}
+template <class _InputIterator, class _OutputIterator>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+_OutputIterator
+__move(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+ return __move_constexpr(__first, __last, __result);
+}
+
template <class _Tp, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename enable_if
<
is_same<typename remove_const<_Tp>::type, _Up>::value &&
>::type
__move(_Tp* __first, _Tp* __last, _Up* __result)
{
+ if (__libcpp_is_constant_evaluated())
+ return __move_constexpr(__first, __last, __result);
const size_t __n = static_cast<size_t>(__last - __first);
if (__n > 0)
_VSTD::memmove(__result, __first, __n * sizeof(_Up));
}
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
move(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
// move_backward
+// __move_backward_constexpr exists so that __move_backward doesn't call itself when delegating to
+// the constexpr version of __move_backward.
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_OutputIterator
-__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+__move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
while (__first != __last)
*--__result = _VSTD::move(*--__last);
return __result;
}
+template <class _InputIterator, class _OutputIterator>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+_OutputIterator
+__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+ return __move_backward_constexpr(__first, __last, __result);
+}
+
template <class _Tp, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename enable_if
<
is_same<typename remove_const<_Tp>::type, _Up>::value &&
>::type
__move_backward(_Tp* __first, _Tp* __last, _Up* __result)
{
+ if (__libcpp_is_constant_evaluated())
+ return __move_backward_constexpr(__first, __last, __result);
const size_t __n = static_cast<size_t>(__last - __first);
if (__n > 0)
{
}
template <class _BidirectionalIterator1, class _BidirectionalIterator2>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_BidirectionalIterator2
move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
_BidirectionalIterator2 __result)
// rotate
template <class _ForwardIterator>
-_ForwardIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
__rotate_left(_ForwardIterator __first, _ForwardIterator __last)
{
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
}
template <class _BidirectionalIterator>
-_BidirectionalIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator
__rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
}
template <class _ForwardIterator>
-_ForwardIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX14 _ForwardIterator
__rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)
{
_ForwardIterator __i = __middle;
template<typename _Integral>
inline _LIBCPP_INLINE_VISIBILITY
-_Integral
+_LIBCPP_CONSTEXPR_AFTER_CXX14 _Integral
__algo_gcd(_Integral __x, _Integral __y)
{
do
}
template<typename _RandomAccessIterator>
-_RandomAccessIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator
__rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
template <class _ForwardIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_ForwardIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
__rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
_VSTD::forward_iterator_tag)
{
template <class _BidirectionalIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_BidirectionalIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator
__rotate(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
_VSTD::bidirectional_iterator_tag)
{
template <class _RandomAccessIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_RandomAccessIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator
__rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
_VSTD::random_access_iterator_tag)
{
template <class _ForwardIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_ForwardIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)
{
if (__first == __middle)
template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy(_Ip, _Ip, _Op);
template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy_backward(_B1, _B1, _B2);
-template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY move(_Ip, _Ip, _Op);
-template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY move_backward(_B1, _B1, _B2);
+template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 move(_Ip, _Ip, _Op);
+template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 move_backward(_B1, _B1, _B2);
#if _LIBCPP_DEBUG_LEVEL < 2
template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
#else
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op copy(_Ip, _Ip, _Op);
template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 copy_backward(_B1, _B1, _B2);
- template <class _Ip, class _Op> friend _Op move(_Ip, _Ip, _Op);
- template <class _B1, class _B2> friend _B2 move_backward(_B1, _B1, _B2);
+ template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op move(_Ip, _Ip, _Op);
+ template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 move_backward(_B1, _B1, _B2);
#if _LIBCPP_DEBUG_LEVEL < 2
template <class _Tp>
- _LIBCPP_CONSTEXPR_IF_NODEBUG friend
+ _LIBCPP_CONSTEXPR friend
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
__unwrap_iter(__wrap_iter<_Tp*>);
#else
template <class _Tp>
- inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
+ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
typename enable_if
<
is_trivially_copy_assignable<_Tp>::value,
// OutIter
// move(InIter first, InIter last, OutIter result);
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10, apple-clang-11
+// UNSUPPORTED: gcc-5, gcc-6, gcc-7, gcc-8
+
#include <algorithm>
#include <cassert>
#include <memory>
#include "test_iterators.h"
template <class InIter, class OutIter>
-void
+_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
test()
{
const unsigned N = 1000;
- int ia[N];
+ int ia[N] = {};
for (unsigned i = 0; i < N; ++i)
ia[i] = i;
int ib[N] = {0};
assert(base(r) == ib+N);
for (unsigned i = 0; i < N; ++i)
assert(ia[i] == ib[i]);
+
+ return true;
}
#if TEST_STD_VER >= 11
test1<std::unique_ptr<int>*, std::unique_ptr<int>*>();
#endif // TEST_STD_VER >= 11
+#if TEST_STD_VER > 17
+ static_assert(test<input_iterator<const int*>, input_iterator<int*> >());
+ static_assert(test<input_iterator<const int*>, forward_iterator<int*> >());
+ static_assert(test<input_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<input_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<input_iterator<const int*>, int*>());
+
+ static_assert(test<forward_iterator<const int*>, input_iterator<int*> >());
+ static_assert(test<forward_iterator<const int*>, forward_iterator<int*> >());
+ static_assert(test<forward_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<forward_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<forward_iterator<const int*>, int*>());
+
+ static_assert(test<bidirectional_iterator<const int*>, input_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, forward_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, int*>());
+
+ static_assert(test<random_access_iterator<const int*>, input_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, forward_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, int*>());
+
+ static_assert(test<const int*, input_iterator<int*> >());
+ static_assert(test<const int*, forward_iterator<int*> >());
+ static_assert(test<const int*, bidirectional_iterator<int*> >());
+ static_assert(test<const int*, random_access_iterator<int*> >());
+ static_assert(test<const int*, int*>());
+#endif // TEST_STD_VER > 17
+
return 0;
}
//
//===----------------------------------------------------------------------===//
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10
+
// <algorithm>
// template<BidirectionalIterator InIter, BidirectionalIterator OutIter>
#include "test_iterators.h"
template <class InIter, class OutIter>
-void
+_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
test()
{
const unsigned N = 1000;
- int ia[N];
+ int ia[N] = {};
for (unsigned i = 0; i < N; ++i)
ia[i] = i;
int ib[N] = {0};
assert(base(r) == ib);
for (unsigned i = 0; i < N; ++i)
assert(ia[i] == ib[i]);
+
+ return true;
}
#if TEST_STD_VER >= 11
test1<std::unique_ptr<int>*, std::unique_ptr<int>*>();
#endif // TEST_STD_VER >= 11
+#if TEST_STD_VER > 17
+ static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<const int*>, int*>());
+
+ static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
+ static_assert(test<random_access_iterator<const int*>, int*>());
+
+ static_assert(test<const int*, bidirectional_iterator<int*> >());
+ static_assert(test<const int*, random_access_iterator<int*> >());
+ static_assert(test<const int*, int*>());
+#endif // TEST_STD_VER > 17
+
return 0;
}
// Iter
// rotate(Iter first, Iter middle, Iter last);
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10
+
#include <algorithm>
#include <cassert>
#include <memory>
#include "test_iterators.h"
template <class Iter>
-void
+_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
test()
{
int ia[] = {0};
assert(ig[3] == 0);
assert(ig[4] == 1);
assert(ig[5] == 2);
+
+ return true;
}
#if TEST_STD_VER >= 11
#endif
+#if TEST_STD_VER > 17
+ static_assert(test<forward_iterator<int*> >());
+ static_assert(test<bidirectional_iterator<int*> >());
+ static_assert(test<random_access_iterator<int*> >());
+ static_assert(test<int*>());
+#endif // TEST_STD_VER > 17
+
return 0;
}
// constexpr OutIter // constexpr after C++17
// rotate_copy(InIter first, InIter middle, InIter last, OutIter result);
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10
+
#include <algorithm>
#include <cassert>
//
// REQUIRES: long_tests
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10
+
// <algorithm>
// template<InputIterator InIter1, InputIterator InIter2, typename OutIter>
//
// REQUIRES: long_tests
+// Older compilers don't support std::is_constant_evaluated
+// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
+// UNSUPPORTED: apple-clang-9, apple-clang-10
+
// <algorithm>
// template<InputIterator InIter1, InputIterator InIter2, typename OutIter,
<p>The missing bits in P0600 are in [mem.res.class], [mem.poly.allocator.class], and [container.node.overview]</p>
-<p>The missing bits in P0202 are in <tt>copy</tt>, <tt>copy_backwards</tt>, <tt>move</tt>, and <tt>move_backwards</tt> (and the ones that call them: <tt>copy_n</tt>, <tt>rotate_copy</tt>, <tt>merge</tt>, <tt>set_union</tt>, <tt>set_difference</tt>, and <tt>set_symmetric_difference</tt>). This is because the first four algorithms have specializations that call <tt>memmove</tt> which is not constexpr. See <a href="https://bugs.llvm.org/show_bug.cgi?id=25165">Bug 25165</a></p>
+<p>The missing bits in P0202 are in <tt>copy</tt> and <tt>copy_backwards</tt> (and the ones that call them: <tt>copy_n</tt>, <tt>set_union</tt>, <tt>set_difference</tt>, and <tt>set_symmetric_difference</tt>). This is because the first two algorithms have specializations that call <tt>memmove</tt> which is not constexpr. See <a href="https://bugs.llvm.org/show_bug.cgi?id=25165">Bug 25165</a></p>
+
<h3>Library Working group Issues Status</h3>
<!-- <I>Note: "NAD" means that the issue was deemed "Not a defect"</I> -->