Commit 14098cf6 authored by Arthur O'Dwyer's avatar Arthur O'Dwyer
Browse files

[libc++] [P0202] constexpr set_union, set_difference, set_symmetric_difference, merge

These had been waiting on the ability to use `std::copy` from
constexpr code (which in turn had been waiting on the ability to
use `is_constant_evaluated()` to switch between `memmove` and non-`memmove`
implementations of `std::copy`). That work landed a while ago,
so these algorithms can all be constexpr in C++20 now.

Simultaneously, update the tests for the set algorithms.

- Use an element type with "equivalent but not identical" values.
- The custom-comparator tests now pass something different from `operator<`.
- Make the constexpr coverage match the non-constexpr coverage.

Differential Revision: https://reviews.llvm.org/D92255
parent c75c6549
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ Paper Status

.. note::

   .. [#note-P0202] P0202: The missing bits in P0202 are in ``copy`` and ``copy_backwards`` (and the ones that call them: ``copy_n``, ``set_union``, ``set_difference``, and ``set_symmetric_difference``). This is because the first two algorithms have specializations that call ``memmove`` which is not constexpr. See `Bug 25165 <https://bugs.llvm.org/show_bug.cgi?id=25165>`__
   .. [#note-P0600] P0600: The missing bits in P0600 are in |sect|\ [mem.res.class], |sect|\ [mem.poly.allocator.class], and |sect|\ [container.node.overview].
   .. [#note-P0966] P0966: It was previously erroneously marked as complete in version 8.0. See `bug 45368 <https://llvm.org/PR45368>`__.

+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
"","","","","",""
"`P0020R6 <https://wg21.link/P0020R6>`__","LWG","Floating Point Atomic","Albuquerque","",""
"`P0053R7 <https://wg21.link/P0053R7>`__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","",""
"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|In Progress| [#note-P0202]_","7.0"
"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|Complete|","12.0"
"`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|In Progress|","7.0"
"`P0439R0 <https://wg21.link/P0439R0>`__","LWG","Make ``std::memory_order``\  a scoped enumeration","Albuquerque","|Complete|",""
"`P0457R2 <https://wg21.link/P0457R2>`__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0"
+17 −17
Original line number Diff line number Diff line
@@ -415,12 +415,12 @@ template <class ForwardIterator, class T, class Compare>
    binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp);

template <class InputIterator1, class InputIterator2, class OutputIterator>
    OutputIterator
    constexpr OutputIterator                          // constexpr in C++20
    merge(InputIterator1 first1, InputIterator1 last1,
          InputIterator2 first2, InputIterator2 last2, OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
    OutputIterator
    constexpr OutputIterator                          // constexpr in C++20
    merge(InputIterator1 first1, InputIterator1 last1,
          InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);

@@ -441,12 +441,12 @@ template <class InputIterator1, class InputIterator2, class Compare>
    includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp);

template <class InputIterator1, class InputIterator2, class OutputIterator>
    OutputIterator
    constexpr OutputIterator                          // constexpr in C++20
    set_union(InputIterator1 first1, InputIterator1 last1,
              InputIterator2 first2, InputIterator2 last2, OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
    OutputIterator
    constexpr OutputIterator                          // constexpr in C++20
    set_union(InputIterator1 first1, InputIterator1 last1,
              InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);

@@ -461,22 +461,22 @@ template <class InputIterator1, class InputIterator2, class OutputIterator, clas
                     InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);

template <class InputIterator1, class InputIterator2, class OutputIterator>
    OutputIterator
    constexpr OutputIterator                         // constexpr in C++20
    set_difference(InputIterator1 first1, InputIterator1 last1,
                   InputIterator2 first2, InputIterator2 last2, OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
    OutputIterator
    constexpr OutputIterator                         // constexpr in C++20
    set_difference(InputIterator1 first1, InputIterator1 last1,
                   InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);

template <class InputIterator1, class InputIterator2, class OutputIterator>
    OutputIterator
    constexpr OutputIterator                         // constexpr in C++20
    set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                             InputIterator2 first2, InputIterator2 last2, OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
    OutputIterator
    constexpr OutputIterator                         // constexpr in C++20
    set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                             InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);

@@ -5401,7 +5401,7 @@ includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi
// set_union

template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_OutputIterator
_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
__set_union(_InputIterator1 __first1, _InputIterator1 __last1,
            _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
{
@@ -5426,7 +5426,7 @@ __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_union(_InputIterator1 __first1, _InputIterator1 __last1,
          _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5436,7 +5436,7 @@ set_union(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_union(_InputIterator1 __first1, _InputIterator1 __last1,
          _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
@@ -5495,7 +5495,7 @@ set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
// set_difference

template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_OutputIterator
_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
__set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                 _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
{
@@ -5520,7 +5520,7 @@ __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
               _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5530,7 +5530,7 @@ set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
               _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
@@ -5543,7 +5543,7 @@ set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
// set_symmetric_difference

template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_OutputIterator
_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
__set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                           _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
{
@@ -5573,7 +5573,7 @@ __set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                         _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5583,7 +5583,7 @@ set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
}

template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                         _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
+60 −212
Original line number Diff line number Diff line
@@ -5,12 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: clang-8

// <algorithm>

@@ -18,233 +14,85 @@
//   requires OutputIterator<OutIter, InIter1::reference>
//         && OutputIterator<OutIter, InIter2::reference>
//         && HasLess<InIter2::value_type, InIter1::value_type>
//         && HasLess<InIter1::value_type, InIter2::value_type>
//   constexpr OutIter       // constexpr after C++17
//   merge(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2, OutIter result);
//   merge(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
//         OutIter result);

#include <algorithm>
#include <random>
#include <cassert>

#include "test_macros.h"
#include "test_iterators.h"
#include "../sortable_helpers.h"

#if TEST_STD_VER > 17
TEST_CONSTEXPR bool test_constexpr() {
  int ia[] = {0, 1, 2, 3, 4};
  int ib[] = {2, 4, 6, 8};
  int ic[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};

  auto it = std::merge(std::begin(ia), std::end(ia), std::begin(ib),
                       std::end(ib), std::begin(ic));
  assert(std::distance(std::begin(ic), it) == static_cast<int>(std::size(ia) + std::size(ib)));
  assert(*it == 0);
  assert(std::equal(std::begin(ic), it, std::begin(expected), std::end(expected)));
  return true;
}
#endif

std::mt19937 randomness;

template <class InIter1, class InIter2, class OutIter>
void test() {
template<class T, class Iter1, class Iter2, class OutIter>
TEST_CONSTEXPR_CXX20 void test4()
{
    const T a[] = {11, 33, 31, 41};
    const T b[] = {22, 32, 43, 42, 52};
    {
    unsigned N = 100000;
    int* ia = new int[N];
    int* ib = new int[N];
    int* ic = new int[2*N];
    for (unsigned i = 0; i < N; ++i)
        ia[i] = 2*i;
    for (unsigned i = 0; i < N; ++i)
        ib[i] = 2*i+1;
    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
                           InIter2(ib), InIter2(ib+N), OutIter(ic));
    assert(base(r) == ic+2*N);
    assert(ic[0] == 0);
    assert(ic[2*N-1] == static_cast<int>(2*N-1));
    assert(std::is_sorted(ic, ic+2*N));
    delete [] ic;
    delete [] ib;
    delete [] ia;
        T result[20] = {};
        T expected[] = {11, 22, 33, 31, 32, 41, 43, 42, 52};
        OutIter end = std::merge(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
        for (const T *it = base(end); it != result+20; ++it) {
            assert(it->value == 0);
        }
    }
    {
    unsigned N = 100;
    int* ia = new int[N];
    int* ib = new int[N];
    int* ic = new int[2*N];
    for (unsigned i = 0; i < 2*N; ++i)
        ic[i] = i;
    std::shuffle(ic, ic+2*N, randomness);
    std::copy(ic, ic+N, ia);
    std::copy(ic+N, ic+2*N, ib);
    std::sort(ia, ia+N);
    std::sort(ib, ib+N);
    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
                           InIter2(ib), InIter2(ib+N), OutIter(ic));
    assert(base(r) == ic+2*N);
    assert(ic[0] == 0);
    assert(ic[2*N-1] == static_cast<int>(2*N-1));
    assert(std::is_sorted(ic, ic+2*N));
    delete [] ic;
    delete [] ib;
    delete [] ia;
        T result[20] = {};
        T expected[] = {11, 22, 32, 33, 31, 43, 42, 41, 52};
        OutIter end = std::merge(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
        for (const T *it = base(end); it != result+20; ++it) {
            assert(it->value == 0);
        }
    }
}

int main(int, char**)
template<class T, class Iter1, class Iter2>
TEST_CONSTEXPR_CXX20 void test3()
{
    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
    test<input_iterator<const int*>, input_iterator<const int*>, int*>();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
    test<const int*, forward_iterator<const int*>, int*>();
    test4<T, Iter1, Iter2, output_iterator<T*> >();
    test4<T, Iter1, Iter2, forward_iterator<T*> >();
    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
    test4<T, Iter1, Iter2, T*>();
}

    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
    test<const int*, bidirectional_iterator<const int*>, int*>();
template<class T, class Iter1>
TEST_CONSTEXPR_CXX20 void test2()
{
    test3<T, Iter1, input_iterator<const T*> >();
    test3<T, Iter1, forward_iterator<const T*> >();
    test3<T, Iter1, bidirectional_iterator<const T*> >();
    test3<T, Iter1, random_access_iterator<const T*> >();
    test3<T, Iter1, const T*>();
}

    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
    test<const int*, random_access_iterator<const int*>, int*>();
template<class T>
TEST_CONSTEXPR_CXX20 void test1()
{
    test2<T, input_iterator<const T*> >();
    test2<T, forward_iterator<const T*> >();
    test2<T, bidirectional_iterator<const T*> >();
    test2<T, random_access_iterator<const T*> >();
    test2<T, const T*>();
}

    test<const int*, const int*, output_iterator<int*> >();
    test<const int*, const int*, forward_iterator<int*> >();
    test<const int*, const int*, bidirectional_iterator<int*> >();
    test<const int*, const int*, random_access_iterator<int*> >();
    test<const int*, const int*, int*>();
TEST_CONSTEXPR_CXX20 bool test()
{
    test1<TrivialSortable>();
    test1<NonTrivialSortable>();
    return true;
}

int main(int, char**)
{
    test();
#if TEST_STD_VER > 17
    static_assert(test_constexpr());
    static_assert(test());
#endif

    return 0;
+62 −227

File changed.

Preview size limit exceeded, changes collapsed.

Loading