1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // template<class F, class I> 12 // concept indirectly_unary_invocable; 13 14 #include <iterator> 15 #include <concepts> 16 17 #include "indirectly_readable.h" 18 19 using It = IndirectlyReadable<struct Token>; 20 using R1 = T1<struct ReturnToken>; 21 using R2 = T2<struct ReturnToken>; 22 23 template <class I> 24 struct GoodInvocable { 25 R1 operator()(std::iter_value_t<I>&) const; 26 R2 operator()(std::iter_reference_t<I>) const; 27 R2 operator()(std::iter_common_reference_t<I>) const; 28 }; 29 30 // Should work when all constraints are satisfied 31 static_assert(std::indirectly_unary_invocable<GoodInvocable<It>, It>); 32 33 // Should fail when the iterator is not indirectly_readable 34 struct NotIndirectlyReadable { }; 35 static_assert(!std::indirectly_unary_invocable<GoodInvocable<NotIndirectlyReadable>, NotIndirectlyReadable>); 36 37 // Should fail when the invocable is not copy constructible 38 struct BadInvocable1 { 39 BadInvocable1(BadInvocable1 const&) = delete; 40 template <class T> R1 operator()(T const&) const; 41 }; 42 static_assert(!std::indirectly_unary_invocable<BadInvocable1, It>); 43 44 // Should fail when the invocable can't be called with (iter_value_t&) 45 struct BadInvocable2 { 46 template <class T> R1 operator()(T const&) const; 47 R1 operator()(std::iter_value_t<It>&) const = delete; 48 }; 49 static_assert(!std::indirectly_unary_invocable<BadInvocable2, It>); 50 51 // Should fail when the invocable can't be called with (iter_reference_t) 52 struct BadInvocable3 { 53 template <class T> R1 operator()(T const&) const; 54 R1 operator()(std::iter_reference_t<It>) const = delete; 55 }; 56 static_assert(!std::indirectly_unary_invocable<BadInvocable3, It>); 57 58 // Should fail when the invocable can't be called with (iter_common_reference_t) 59 struct BadInvocable4 { 60 template <class T> R1 operator()(T const&) const; 61 R1 operator()(std::iter_common_reference_t<It>) const = delete; 62 }; 63 static_assert(!std::indirectly_unary_invocable<BadInvocable4, It>); 64 65 // Should fail when the invocable doesn't have a common reference between its return types 66 struct BadInvocable5 { 67 R1 operator()(std::iter_value_t<It>&) const; 68 struct Unrelated { }; 69 Unrelated operator()(std::iter_reference_t<It>) const; 70 R1 operator()(std::iter_common_reference_t<It>) const; 71 }; 72 static_assert(!std::indirectly_unary_invocable<BadInvocable5, It>); 73 74 // Various tests with callables 75 struct S; 76 static_assert(std::indirectly_unary_invocable<int (*)(int), int*>); 77 static_assert(std::indirectly_unary_invocable<int (&)(int), int*>); 78 static_assert(std::indirectly_unary_invocable<int S::*, S*>); 79 static_assert(std::indirectly_unary_invocable<int (S::*)(), S*>); 80 static_assert(std::indirectly_unary_invocable<int (S::*)() const, S*>); 81 static_assert(std::indirectly_unary_invocable<void(*)(int), int*>); 82 83 static_assert(!std::indirectly_unary_invocable<int(int), int*>); // not move constructible 84 static_assert(!std::indirectly_unary_invocable<int (*)(int*, int*), int*>); 85 static_assert(!std::indirectly_unary_invocable<int (&)(int*, int*), int*>); 86 static_assert(!std::indirectly_unary_invocable<int (S::*)(int*), S*>); 87 static_assert(!std::indirectly_unary_invocable<int (S::*)(int*) const, S*>); 88