Commit 13c90a57 authored by Louis Dionne's avatar Louis Dionne
Browse files

[libc++][P0202] Marked algorithms copy/copy_n/copy_if/copy_backward constexpr

Thanks to Michael Park for the patch.

Differential Revision: https://reviews.llvm.org/D68837
parent eb12b3b8
Loading
Loading
Loading
Loading
+47 −19
Original line number Diff line number Diff line
@@ -167,20 +167,20 @@ template <class ForwardIterator, class Size, class T, class BinaryPredicate>
             Size count, const T& value, BinaryPredicate pred);

template <class InputIterator, class OutputIterator>
    OutputIterator
    constexpr OutputIterator      // constexpr in C++20
    copy(InputIterator first, InputIterator last, OutputIterator result);

template<class InputIterator, class OutputIterator, class Predicate>
    OutputIterator
    constexpr OutputIterator      // constexpr in C++20
    copy_if(InputIterator first, InputIterator last,
            OutputIterator result, Predicate pred);

template<class InputIterator, class Size, class OutputIterator>
    OutputIterator
    constexpr OutputIterator      // constexpr in C++20
    copy_n(InputIterator first, Size n, OutputIterator result);

template <class BidirectionalIterator1, class BidirectionalIterator2>
    BidirectionalIterator2
    constexpr BidirectionalIterator2      // constexpr in C++20
    copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last,
                  BidirectionalIterator2 result);

@@ -1631,7 +1631,7 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const

// copy
template <class _Iter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_Iter
__unwrap_iter(_Iter __i)
{
@@ -1639,7 +1639,7 @@ __unwrap_iter(_Iter __i)
}

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
typename enable_if
<
    is_trivially_copy_assignable<_Tp>::value,
@@ -1693,15 +1693,23 @@ __unwrap_iter(__wrap_iter<_Tp*> __i)
#endif  // _LIBCPP_DEBUG_LEVEL < 2

template <class _InputIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
__copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
__copy_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
    for (; __first != __last; ++__first, (void) ++__result)
        *__result = *__first;
    return __result;
}

template <class _InputIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
_OutputIterator
__copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
    return __copy_constexpr(__first, __last, __result);
}

template <class _Tp, class _Up>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
@@ -1719,25 +1727,39 @@ __copy(_Tp* __first, _Tp* __last, _Up* __result)
}

template <class _InputIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
{
    return _VSTD::__copy(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result));
    if (__libcpp_is_constant_evaluated()) {
        return _VSTD::__copy_constexpr(
            __unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result));
    } else {
        return _VSTD::__copy(
            __unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result));
    }
}

// copy_backward

template <class _BidirectionalIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
__copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
__copy_backward_constexpr(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
{
    while (__first != __last)
        *--__result = *--__last;
    return __result;
}

template <class _BidirectionalIterator, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
_OutputIterator
__copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
{
    return __copy_backward_constexpr(__first, __last, __result);
}

template <class _Tp, class _Up>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
@@ -1758,20 +1780,26 @@ __copy_backward(_Tp* __first, _Tp* __last, _Up* __result)
}

template <class _BidirectionalIterator1, class _BidirectionalIterator2>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_BidirectionalIterator2
copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
              _BidirectionalIterator2 __result)
{
    if (__libcpp_is_constant_evaluated()) {
        return _VSTD::__copy_backward_constexpr(__unwrap_iter(__first),
                                                __unwrap_iter(__last),
                                                __unwrap_iter(__result));
    } else {
        return _VSTD::__copy_backward(__unwrap_iter(__first),
                                      __unwrap_iter(__last),
                                      __unwrap_iter(__result));
    }
}

// copy_if

template<class _InputIterator, class _OutputIterator, class _Predicate>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
copy_if(_InputIterator __first, _InputIterator __last,
        _OutputIterator __result, _Predicate __pred)
@@ -1790,7 +1818,7 @@ copy_if(_InputIterator __first, _InputIterator __last,
// copy_n

template<class _InputIterator, class _Size, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
typename enable_if
<
    __is_input_iterator<_InputIterator>::value &&
@@ -1816,7 +1844,7 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
}

template<class _InputIterator, class _Size, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
typename enable_if
<
    __is_random_access_iterator<_InputIterator>::value,
+4 −4
Original line number Diff line number Diff line
@@ -1304,8 +1304,8 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
__wrap_iter<_Iter>
operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT;

template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY copy(_Ip, _Ip, _Op);
template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY copy_backward(_B1, _B1, _B2);
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);

@@ -1515,8 +1515,8 @@ private:
    __wrap_iter<_Iter1>
    operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT;

    template <class _Ip, class _Op> friend _Op copy(_Ip, _Ip, _Op);
    template <class _B1, class _B2> friend _B2 copy_backward(_B1, _B1, _B2);
    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);

+44 −48
Original line number Diff line number Diff line
@@ -18,21 +18,9 @@
#include "test_macros.h"
#include "test_iterators.h"

// #if TEST_STD_VER > 17
// TEST_CONSTEXPR bool test_constexpr() {
//     int ia[] = {1, 2, 3, 4, 5};
//     int ic[] = {6, 6, 6, 6, 6, 6, 6};
//
//     auto p = std::copy(std::begin(ia), std::end(ia), std::begin(ic));
//     return std::equal(std::begin(ia), std::end(ia), std::begin(ic), p)
//         && std::all_of(p, std::end(ic), [](int a){return a == 6;})
//         ;
//     }
// #endif

template <class InIter, class OutIter>
void
test()
TEST_CONSTEXPR_CXX20 void
test_copy()
{
    const unsigned N = 1000;
    int ia[N];
@@ -46,46 +34,54 @@ test()
        assert(ia[i] == ib[i]);
}

int main(int, char**)
TEST_CONSTEXPR_CXX20 bool
test()
{
    test<input_iterator<const int*>, output_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<int*> >();
    test<input_iterator<const int*>, forward_iterator<int*> >();
    test<input_iterator<const int*>, bidirectional_iterator<int*> >();
    test<input_iterator<const int*>, random_access_iterator<int*> >();
    test<input_iterator<const int*>, int*>();
    test_copy<input_iterator<const int*>, output_iterator<int*> >();
    test_copy<input_iterator<const int*>, input_iterator<int*> >();
    test_copy<input_iterator<const int*>, forward_iterator<int*> >();
    test_copy<input_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy<input_iterator<const int*>, random_access_iterator<int*> >();
    test_copy<input_iterator<const int*>, int*>();

    test<forward_iterator<const int*>, output_iterator<int*> >();
    test<forward_iterator<const int*>, input_iterator<int*> >();
    test<forward_iterator<const int*>, forward_iterator<int*> >();
    test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
    test<forward_iterator<const int*>, random_access_iterator<int*> >();
    test<forward_iterator<const int*>, int*>();
    test_copy<forward_iterator<const int*>, output_iterator<int*> >();
    test_copy<forward_iterator<const int*>, input_iterator<int*> >();
    test_copy<forward_iterator<const int*>, forward_iterator<int*> >();
    test_copy<forward_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy<forward_iterator<const int*>, random_access_iterator<int*> >();
    test_copy<forward_iterator<const int*>, int*>();

    test<bidirectional_iterator<const int*>, output_iterator<int*> >();
    test<bidirectional_iterator<const int*>, input_iterator<int*> >();
    test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
    test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test<bidirectional_iterator<const int*>, int*>();
    test_copy<bidirectional_iterator<const int*>, output_iterator<int*> >();
    test_copy<bidirectional_iterator<const int*>, input_iterator<int*> >();
    test_copy<bidirectional_iterator<const int*>, forward_iterator<int*> >();
    test_copy<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test_copy<bidirectional_iterator<const int*>, int*>();

    test<random_access_iterator<const int*>, output_iterator<int*> >();
    test<random_access_iterator<const int*>, input_iterator<int*> >();
    test<random_access_iterator<const int*>, forward_iterator<int*> >();
    test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test<random_access_iterator<const int*>, int*>();
    test_copy<random_access_iterator<const int*>, output_iterator<int*> >();
    test_copy<random_access_iterator<const int*>, input_iterator<int*> >();
    test_copy<random_access_iterator<const int*>, forward_iterator<int*> >();
    test_copy<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test_copy<random_access_iterator<const int*>, int*>();

    test<const int*, output_iterator<int*> >();
    test<const int*, input_iterator<int*> >();
    test<const int*, forward_iterator<int*> >();
    test<const int*, bidirectional_iterator<int*> >();
    test<const int*, random_access_iterator<int*> >();
    test<const int*, int*>();
    test_copy<const int*, output_iterator<int*> >();
    test_copy<const int*, input_iterator<int*> >();
    test_copy<const int*, forward_iterator<int*> >();
    test_copy<const int*, bidirectional_iterator<int*> >();
    test_copy<const int*, random_access_iterator<int*> >();
    test_copy<const int*, int*>();

  return true;
}

int main(int, char**)
{
    test();

// #if TEST_STD_VER > 17
//     static_assert(test_constexpr());
// #endif
#if TEST_STD_VER > 17
    static_assert(test());
#endif

  return 0;
}
+23 −28
Original line number Diff line number Diff line
@@ -20,22 +20,9 @@
#include "test_iterators.h"
#include "user_defined_integral.h"

// #if TEST_STD_VER > 17
// TEST_CONSTEXPR bool test_constexpr() {
//     int ia[] = {1, 2, 3, 4, 5};
//     int ic[] = {6, 6, 6, 6, 6, 6, 6};
//
//     size_t N = std::size(ia);
//     auto p = std::copy_backward(std::begin(ia), std::end(ia), std::begin(ic) + N);
//     return std::equal(std::begin(ic), p, std::begin(ia))
//         && std::all_of(p, std::end(ic), [](int a){return a == 6;})
//         ;
//     }
// #endif

template <class InIter, class OutIter>
void
test()
TEST_CONSTEXPR_CXX20 void
test_copy_backward()
{
    const unsigned N = 1000;
    int ia[N];
@@ -49,23 +36,31 @@ test()
        assert(ia[i] == ib[i]);
}

int main(int, char**)
TEST_CONSTEXPR_CXX20 bool
test()
{
    test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test<bidirectional_iterator<const int*>, int*>();
    test_copy_backward<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_backward<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_backward<bidirectional_iterator<const int*>, int*>();

    test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test<random_access_iterator<const int*>, int*>();
    test_copy_backward<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_backward<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_backward<random_access_iterator<const int*>, int*>();

    test<const int*, bidirectional_iterator<int*> >();
    test<const int*, random_access_iterator<int*> >();
    test<const int*, int*>();
    test_copy_backward<const int*, bidirectional_iterator<int*> >();
    test_copy_backward<const int*, random_access_iterator<int*> >();
    test_copy_backward<const int*, int*>();

    return true;
}

int main(int, char**)
{
    test();

// #if TEST_STD_VER > 17
//     static_assert(test_constexpr());
// #endif
#if TEST_STD_VER > 17
    static_assert(test());
#endif

  return 0;
}
+49 −53
Original line number Diff line number Diff line
@@ -20,26 +20,14 @@
#include "test_macros.h"
#include "test_iterators.h"

// #if TEST_STD_VER > 17
// TEST_CONSTEXPR bool test_constexpr() {
//     int ia[] = {2, 4, 6, 8, 6};
//     int ic[] = {0, 0, 0, 0, 0, 0};
//
//     auto p = std::copy_if(std::begin(ia), std::end(ia), std::begin(ic), is6);
//     return std::all_of(std::begin(ic), p, [](int a){return a == 6;})
//         && std::all_of(p, std::end(ic),   [](int a){return a == 0;})
//         ;
//     }
// #endif

struct Pred
{
    bool operator()(int i) {return i % 3 == 0;}
    TEST_CONSTEXPR_CXX14 bool operator()(int i) {return i % 3 == 0;}
};

template <class InIter, class OutIter>
void
test()
TEST_CONSTEXPR_CXX20 void
test_copy_if()
{
    const unsigned N = 1000;
    int ia[N];
@@ -53,46 +41,54 @@ test()
        assert(ib[i] % 3 == 0);
}

TEST_CONSTEXPR_CXX20 bool
test()
{
    test_copy_if<input_iterator<const int*>, output_iterator<int*> >();
    test_copy_if<input_iterator<const int*>, input_iterator<int*> >();
    test_copy_if<input_iterator<const int*>, forward_iterator<int*> >();
    test_copy_if<input_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_if<input_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_if<input_iterator<const int*>, int*>();

    test_copy_if<forward_iterator<const int*>, output_iterator<int*> >();
    test_copy_if<forward_iterator<const int*>, input_iterator<int*> >();
    test_copy_if<forward_iterator<const int*>, forward_iterator<int*> >();
    test_copy_if<forward_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_if<forward_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_if<forward_iterator<const int*>, int*>();

    test_copy_if<bidirectional_iterator<const int*>, output_iterator<int*> >();
    test_copy_if<bidirectional_iterator<const int*>, input_iterator<int*> >();
    test_copy_if<bidirectional_iterator<const int*>, forward_iterator<int*> >();
    test_copy_if<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_if<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_if<bidirectional_iterator<const int*>, int*>();

    test_copy_if<random_access_iterator<const int*>, output_iterator<int*> >();
    test_copy_if<random_access_iterator<const int*>, input_iterator<int*> >();
    test_copy_if<random_access_iterator<const int*>, forward_iterator<int*> >();
    test_copy_if<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test_copy_if<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test_copy_if<random_access_iterator<const int*>, int*>();

    test_copy_if<const int*, output_iterator<int*> >();
    test_copy_if<const int*, input_iterator<int*> >();
    test_copy_if<const int*, forward_iterator<int*> >();
    test_copy_if<const int*, bidirectional_iterator<int*> >();
    test_copy_if<const int*, random_access_iterator<int*> >();
    test_copy_if<const int*, int*>();

  return true;
}

int main(int, char**)
{
    test<input_iterator<const int*>, output_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<int*> >();
    test<input_iterator<const int*>, forward_iterator<int*> >();
    test<input_iterator<const int*>, bidirectional_iterator<int*> >();
    test<input_iterator<const int*>, random_access_iterator<int*> >();
    test<input_iterator<const int*>, int*>();

    test<forward_iterator<const int*>, output_iterator<int*> >();
    test<forward_iterator<const int*>, input_iterator<int*> >();
    test<forward_iterator<const int*>, forward_iterator<int*> >();
    test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
    test<forward_iterator<const int*>, random_access_iterator<int*> >();
    test<forward_iterator<const int*>, int*>();

    test<bidirectional_iterator<const int*>, output_iterator<int*> >();
    test<bidirectional_iterator<const int*>, input_iterator<int*> >();
    test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
    test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test<bidirectional_iterator<const int*>, int*>();

    test<random_access_iterator<const int*>, output_iterator<int*> >();
    test<random_access_iterator<const int*>, input_iterator<int*> >();
    test<random_access_iterator<const int*>, forward_iterator<int*> >();
    test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test<random_access_iterator<const int*>, random_access_iterator<int*> >();
    test<random_access_iterator<const int*>, int*>();

    test<const int*, output_iterator<int*> >();
    test<const int*, input_iterator<int*> >();
    test<const int*, forward_iterator<int*> >();
    test<const int*, bidirectional_iterator<int*> >();
    test<const int*, random_access_iterator<int*> >();
    test<const int*, int*>();

// #if TEST_STD_VER > 17
//     static_assert(test_constexpr());
// #endif
    test();

#if TEST_STD_VER > 17
    static_assert(test());
#endif

  return 0;
}
Loading