//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // template // concept mergeable = see below; // since C++20 #include #include #include "test_iterators.h" #include "test_macros.h" using CompDefault = std::ranges::less; using CompInt = bool(*)(int, int); using ProjDefault = std::identity; using Input = cpp20_input_iterator; static_assert( std::input_iterator); using InputLong = cpp20_input_iterator; static_assert( std::input_iterator); using Output = cpp17_output_iterator; static_assert( std::weakly_incrementable); static_assert( std::indirectly_copyable); static_assert( std::indirectly_copyable); static_assert( std::indirect_strict_weak_order); static_assert( std::indirect_strict_weak_order); static_assert( std::indirect_strict_weak_order); static_assert( std::indirect_strict_weak_order); // All requirements satisfied. static_assert( std::mergeable); static_assert( std::mergeable); static_assert( std::mergeable); // Non-default projections. struct Foo {}; using ProjFooToInt = int(*)(Foo); using ProjFooToLong = long(*)(Foo); static_assert( std::indirect_strict_weak_order, std::projected>); static_assert( std::mergeable); static_assert( std::indirect_strict_weak_order, std::projected>); static_assert( std::mergeable); // I1 or I2 is not an input iterator. static_assert(!std::input_iterator); static_assert(!std::mergeable); static_assert(!std::mergeable); // O is not weakly incrementable. struct NotWeaklyIncrementable { int& operator*() const; }; static_assert(!std::weakly_incrementable); static_assert( std::indirectly_copyable); static_assert( std::indirect_strict_weak_order); static_assert(!std::mergeable); // I1 or I2 is not indirectly copyable into O. struct AssignableOnlyFromInt { AssignableOnlyFromInt& operator=(int); template AssignableOnlyFromInt& operator=(T) = delete; }; using OutputOnlyInt = cpp17_output_iterator; static_assert( std::weakly_incrementable); static_assert( std::indirectly_copyable); static_assert(!std::indirectly_copyable); static_assert( std::indirect_strict_weak_order); static_assert( std::mergeable); static_assert(!std::mergeable); static_assert(!std::mergeable); // No indirect strict weak order between I1 and I2 (bad comparison functor). using GoodComp = bool(*)(int, int); static_assert( std::indirect_strict_weak_order); static_assert( std::mergeable); using BadComp = bool(*)(int*, int*); static_assert(!std::indirect_strict_weak_order); static_assert(!std::mergeable); // No indirect strict weak order between I1 and I2 (bad projection). using ToInt = int(*)(int); using ToPtr = int*(*)(int); static_assert( std::mergeable); static_assert( std::mergeable); static_assert(!std::mergeable); static_assert(!std::mergeable); static_assert(!std::mergeable); static_assert(!std::mergeable); // A projection that only supports non-const references and has a non-const `operator()` still has to work. struct ProjectionOnlyMutable { int operator()(int&); int operator()(int&&) const = delete; }; static_assert( std::mergeable); // The output is weakly incrementable but not an output iterator. struct WeaklyIncrementable { using value_type = int; using difference_type = int; int& operator*() const; WeaklyIncrementable& operator++(); // `output_iterator` requires `i++` to return an iterator, // while `weakly_incrementable` requires only that `i++` be well-formed. void operator++(int); }; static_assert( std::weakly_incrementable); static_assert( std::indirectly_copyable); static_assert(!std::output_iterator); static_assert( std::mergeable);