]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp
Vendor import of libc++ trunk r290819:
[FreeBSD/FreeBSD.git] / test / std / utilities / function.objects / func.not_fn / not_fn.pass.cpp
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11
12 // template <class F> unspecified not_fn(F&& f);
13
14 #include <functional>
15 #include <type_traits>
16 #include <string>
17 #include <cassert>
18
19 #include "test_macros.h"
20 #include "type_id.h"
21
22
23 ///////////////////////////////////////////////////////////////////////////////
24 //                       CALLABLE TEST TYPES
25 ///////////////////////////////////////////////////////////////////////////////
26
27 bool returns_true() { return true; }
28
29 template <class Ret = bool>
30 struct MoveOnlyCallable {
31   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
32   MoveOnlyCallable(MoveOnlyCallable&& other)
33       : value(other.value)
34   { other.value = !other.value; }
35
36   template <class ...Args>
37   Ret operator()(Args&&...) { return Ret{value}; }
38
39   explicit MoveOnlyCallable(bool x) : value(x) {}
40   Ret value;
41 };
42
43 template <class Ret = bool>
44 struct CopyCallable {
45   CopyCallable(CopyCallable const& other)
46       : value(other.value) {}
47
48   CopyCallable(CopyCallable&& other)
49       : value(other.value) { other.value = !other.value; }
50
51   template <class ...Args>
52   Ret operator()(Args&&...) { return Ret{value}; }
53
54   explicit CopyCallable(bool x) : value(x)  {}
55   Ret value;
56 };
57
58
59 template <class Ret = bool>
60 struct ConstCallable {
61   ConstCallable(ConstCallable const& other)
62       : value(other.value) {}
63
64   ConstCallable(ConstCallable&& other)
65       : value(other.value) { other.value = !other.value; }
66
67   template <class ...Args>
68   Ret operator()(Args&&...) const { return Ret{value}; }
69
70   explicit ConstCallable(bool x) : value(x)  {}
71   Ret value;
72 };
73
74
75
76 template <class Ret = bool>
77 struct NoExceptCallable {
78   NoExceptCallable(NoExceptCallable const& other)
79       : value(other.value) {}
80
81   template <class ...Args>
82   Ret operator()(Args&&...) noexcept { return Ret{value}; }
83
84   template <class ...Args>
85   Ret operator()(Args&&...) const noexcept { return Ret{value}; }
86
87   explicit NoExceptCallable(bool x) : value(x)  {}
88   Ret value;
89 };
90
91 struct CopyAssignableWrapper {
92   CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
93   CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
94   CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
95   CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
96
97   template <class ...Args>
98   bool operator()(Args&&...) { return value; }
99
100   explicit CopyAssignableWrapper(bool x) : value(x) {}
101   bool value;
102 };
103
104
105 struct MoveAssignableWrapper {
106   MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
107   MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
108   MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
109   MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
110
111   template <class ...Args>
112   bool operator()(Args&&...) { return value; }
113
114   explicit MoveAssignableWrapper(bool x) : value(x) {}
115   bool value;
116 };
117
118 struct MemFunCallable {
119   explicit MemFunCallable(bool x) : value(x) {}
120
121   bool return_value() const { return value; }
122   bool return_value_nc() { return value; }
123   bool value;
124 };
125
126 enum CallType : unsigned {
127   CT_None,
128   CT_NonConst = 1,
129   CT_Const = 2,
130   CT_LValue = 4,
131   CT_RValue = 8
132 };
133
134 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
135     return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
136 }
137
138 struct ForwardingCallObject {
139
140   template <class ...Args>
141   bool operator()(Args&&...) & {
142       set_call<Args&&...>(CT_NonConst | CT_LValue);
143       return true;
144   }
145
146   template <class ...Args>
147   bool operator()(Args&&...) const & {
148       set_call<Args&&...>(CT_Const | CT_LValue);
149       return true;
150   }
151
152   // Don't allow the call operator to be invoked as an rvalue.
153   template <class ...Args>
154   bool operator()(Args&&...) && {
155       set_call<Args&&...>(CT_NonConst | CT_RValue);
156       return true;
157   }
158
159   template <class ...Args>
160   bool operator()(Args&&...) const && {
161       set_call<Args&&...>(CT_Const | CT_RValue);
162       return true;
163   }
164
165   template <class ...Args>
166   static void set_call(CallType type) {
167       assert(last_call_type == CT_None);
168       assert(last_call_args == nullptr);
169       last_call_type = type;
170       last_call_args = &makeArgumentID<Args...>();
171   }
172
173   template <class ...Args>
174   static bool check_call(CallType type) {
175       bool result =
176            last_call_type == type
177         && last_call_args
178         && *last_call_args == makeArgumentID<Args...>();
179       last_call_type = CT_None;
180       last_call_args = nullptr;
181       return result;
182   }
183
184   static CallType      last_call_type;
185   static TypeID const* last_call_args;
186 };
187
188 CallType ForwardingCallObject::last_call_type = CT_None;
189 TypeID const* ForwardingCallObject::last_call_args = nullptr;
190
191
192
193 ///////////////////////////////////////////////////////////////////////////////
194 //                        BOOL TEST TYPES
195 ///////////////////////////////////////////////////////////////////////////////
196
197 struct EvilBool {
198   static int bang_called;
199
200   EvilBool(EvilBool const&) = default;
201   EvilBool(EvilBool&&) = default;
202
203   friend EvilBool operator!(EvilBool const& other) {
204     ++bang_called;
205     return EvilBool{!other.value};
206   }
207
208 private:
209   friend struct MoveOnlyCallable<EvilBool>;
210   friend struct CopyCallable<EvilBool>;
211   friend struct NoExceptCallable<EvilBool>;
212
213   explicit EvilBool(bool x) : value(x) {}
214   EvilBool& operator=(EvilBool const& other) = default;
215
216 public:
217   bool value;
218 };
219
220 int EvilBool::bang_called = 0;
221
222 struct ExplicitBool {
223   ExplicitBool(ExplicitBool const&) = default;
224   ExplicitBool(ExplicitBool&&) = default;
225
226   explicit operator bool() const { return value; }
227
228 private:
229   friend struct MoveOnlyCallable<ExplicitBool>;
230   friend struct CopyCallable<ExplicitBool>;
231
232   explicit ExplicitBool(bool x) : value(x) {}
233   ExplicitBool& operator=(bool x) {
234       value = x;
235       return *this;
236   }
237
238   bool value;
239 };
240
241
242 struct NoExceptEvilBool {
243   NoExceptEvilBool(NoExceptEvilBool const&) = default;
244   NoExceptEvilBool(NoExceptEvilBool&&) = default;
245   NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
246
247   explicit NoExceptEvilBool(bool x) : value(x) {}
248
249   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
250     return NoExceptEvilBool{!other.value};
251   }
252
253   bool value;
254 };
255
256
257
258 void constructor_tests()
259 {
260     {
261         using T = MoveOnlyCallable<bool>;
262         T value(true);
263         using RetT = decltype(std::not_fn(std::move(value)));
264         static_assert(std::is_move_constructible<RetT>::value, "");
265         static_assert(!std::is_copy_constructible<RetT>::value, "");
266         static_assert(!std::is_move_assignable<RetT>::value, "");
267         static_assert(!std::is_copy_assignable<RetT>::value, "");
268         auto ret = std::not_fn(std::move(value));
269         // test it was moved from
270         assert(value.value == false);
271         // test that ret() negates the original value 'true'
272         assert(ret() == false);
273         assert(ret(0, 0.0, "blah") == false);
274         // Move ret and test that it was moved from and that ret2 got the
275         // original value.
276         auto ret2 = std::move(ret);
277         assert(ret() == true);
278         assert(ret2() == false);
279         assert(ret2(42) == false);
280     }
281     {
282         using T = CopyCallable<bool>;
283         T value(false);
284         using RetT = decltype(std::not_fn(value));
285         static_assert(std::is_move_constructible<RetT>::value, "");
286         static_assert(std::is_copy_constructible<RetT>::value, "");
287         static_assert(!std::is_move_assignable<RetT>::value, "");
288         static_assert(!std::is_copy_assignable<RetT>::value, "");
289         auto ret = std::not_fn(value);
290         // test that value is unchanged (copied not moved)
291         assert(value.value == false);
292         // test 'ret' has the original value
293         assert(ret() == true);
294         assert(ret(42, 100) == true);
295         // move from 'ret' and check that 'ret2' has the original value.
296         auto ret2 = std::move(ret);
297         assert(ret() == false);
298         assert(ret2() == true);
299         assert(ret2("abc") == true);
300     }
301     {
302         using T = CopyAssignableWrapper;
303         T value(true);
304         T value2(false);
305         using RetT = decltype(std::not_fn(value));
306         static_assert(std::is_move_constructible<RetT>::value, "");
307         static_assert(std::is_copy_constructible<RetT>::value, "");
308         static_assert(std::is_move_assignable<RetT>::value, "");
309         static_assert(std::is_copy_assignable<RetT>::value, "");
310         auto ret = std::not_fn(value);
311         assert(ret() == false);
312         auto ret2 = std::not_fn(value2);
313         assert(ret2() == true);
314         ret = ret2;
315         assert(ret() == true);
316         assert(ret2() == true);
317     }
318     {
319         using T = MoveAssignableWrapper;
320         T value(true);
321         T value2(false);
322         using RetT = decltype(std::not_fn(std::move(value)));
323         static_assert(std::is_move_constructible<RetT>::value, "");
324         static_assert(!std::is_copy_constructible<RetT>::value, "");
325         static_assert(std::is_move_assignable<RetT>::value, "");
326         static_assert(!std::is_copy_assignable<RetT>::value, "");
327         auto ret = std::not_fn(std::move(value));
328         assert(ret() == false);
329         auto ret2 = std::not_fn(std::move(value2));
330         assert(ret2() == true);
331         ret = std::move(ret2);
332         assert(ret() == true);
333     }
334 }
335
336 void return_type_tests()
337 {
338     using std::is_same;
339     {
340         using T = CopyCallable<bool>;
341         auto ret = std::not_fn(T{false});
342         static_assert(is_same<decltype(ret()), bool>::value, "");
343         static_assert(is_same<decltype(ret("abc")), bool>::value, "");
344         assert(ret() == true);
345     }
346     {
347         using T = CopyCallable<ExplicitBool>;
348         auto ret = std::not_fn(T{true});
349         static_assert(is_same<decltype(ret()), bool>::value, "");
350         static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
351         assert(ret() == false);
352     }
353     {
354         using T = CopyCallable<EvilBool>;
355         auto ret = std::not_fn(T{false});
356         static_assert(is_same<decltype(ret()), EvilBool>::value, "");
357         EvilBool::bang_called = 0;
358         auto value_ret = ret();
359         assert(EvilBool::bang_called == 1);
360         assert(value_ret.value == true);
361         ret();
362         assert(EvilBool::bang_called == 2);
363     }
364 }
365
366 // Other tests only test using objects with call operators. Test various
367 // other callable types here.
368 void other_callable_types_test()
369 {
370     { // test with function pointer
371         auto ret = std::not_fn(returns_true);
372         assert(ret() == false);
373     }
374     { // test with lambda
375         auto returns_value = [](bool value) { return value; };
376         auto ret = std::not_fn(returns_value);
377         assert(ret(true) == false);
378         assert(ret(false) == true);
379     }
380     { // test with pointer to member function
381         MemFunCallable mt(true);
382         const MemFunCallable mf(false);
383         auto ret = std::not_fn(&MemFunCallable::return_value);
384         assert(ret(mt) == false);
385         assert(ret(mf) == true);
386         assert(ret(&mt) == false);
387         assert(ret(&mf) == true);
388     }
389     { // test with pointer to member function
390         MemFunCallable mt(true);
391         MemFunCallable mf(false);
392         auto ret = std::not_fn(&MemFunCallable::return_value_nc);
393         assert(ret(mt) == false);
394         assert(ret(mf) == true);
395         assert(ret(&mt) == false);
396         assert(ret(&mf) == true);
397     }
398     { // test with pointer to member data
399         MemFunCallable mt(true);
400         const MemFunCallable mf(false);
401         auto ret = std::not_fn(&MemFunCallable::value);
402         assert(ret(mt) == false);
403         assert(ret(mf) == true);
404         assert(ret(&mt) == false);
405         assert(ret(&mf) == true);
406     }
407 }
408
409 void throws_in_constructor_test()
410 {
411 #ifndef TEST_HAS_NO_EXCEPTIONS
412     struct ThrowsOnCopy {
413       ThrowsOnCopy(ThrowsOnCopy const&) {
414         throw 42;
415       }
416       ThrowsOnCopy() = default;
417       bool operator()() const { assert(false); }
418     };
419     {
420         ThrowsOnCopy cp;
421         try {
422             std::not_fn(cp);
423             assert(false);
424         } catch (int const& value) {
425             assert(value == 42);
426         }
427     }
428 #endif
429 }
430
431 void call_operator_sfinae_test() {
432     { // wrong number of arguments
433         using T = decltype(std::not_fn(returns_true));
434         static_assert(std::is_callable<T()>::value, ""); // callable only with no args
435         static_assert(!std::is_callable<T(bool)>::value, "");
436     }
437     { // violates const correctness (member function pointer)
438         using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
439         static_assert(std::is_callable<T(MemFunCallable&)>::value, "");
440         static_assert(!std::is_callable<T(const MemFunCallable&)>::value, "");
441     }
442     { // violates const correctness (call object)
443         using Obj = CopyCallable<bool>;
444         using NCT = decltype(std::not_fn(Obj{true}));
445         using CT = const NCT;
446         static_assert(std::is_callable<NCT()>::value, "");
447         static_assert(!std::is_callable<CT()>::value, "");
448     }
449     { // returns bad type with no operator!
450         auto fn = [](auto x) { return x; };
451         using T = decltype(std::not_fn(fn));
452         static_assert(std::is_callable<T(bool)>::value, "");
453         static_assert(!std::is_callable<T(std::string)>::value, "");
454     }
455 }
456
457 void call_operator_forwarding_test()
458 {
459     using Fn = ForwardingCallObject;
460     auto obj = std::not_fn(Fn{});
461     const auto& c_obj = obj;
462     { // test zero args
463         obj();
464         assert(Fn::check_call<>(CT_NonConst | CT_LValue));
465         std::move(obj)();
466         assert(Fn::check_call<>(CT_NonConst | CT_RValue));
467         c_obj();
468         assert(Fn::check_call<>(CT_Const | CT_LValue));
469         std::move(c_obj)();
470         assert(Fn::check_call<>(CT_Const | CT_RValue));
471     }
472     { // test value categories
473         int x = 42;
474         const int cx = 42;
475         obj(x);
476         assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
477         obj(cx);
478         assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
479         obj(std::move(x));
480         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
481         obj(std::move(cx));
482         assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
483         obj(42);
484         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
485     }
486     { // test value categories - rvalue
487         int x = 42;
488         const int cx = 42;
489         std::move(obj)(x);
490         assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
491         std::move(obj)(cx);
492         assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue));
493         std::move(obj)(std::move(x));
494         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
495         std::move(obj)(std::move(cx));
496         assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue));
497         std::move(obj)(42);
498         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
499     }
500     { // test value categories - const call
501         int x = 42;
502         const int cx = 42;
503         c_obj(x);
504         assert(Fn::check_call<int&>(CT_Const | CT_LValue));
505         c_obj(cx);
506         assert(Fn::check_call<const int&>(CT_Const | CT_LValue));
507         c_obj(std::move(x));
508         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
509         c_obj(std::move(cx));
510         assert(Fn::check_call<const int&&>(CT_Const | CT_LValue));
511         c_obj(42);
512         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
513     }
514     { // test value categories - const call rvalue
515         int x = 42;
516         const int cx = 42;
517         std::move(c_obj)(x);
518         assert(Fn::check_call<int&>(CT_Const | CT_RValue));
519         std::move(c_obj)(cx);
520         assert(Fn::check_call<const int&>(CT_Const | CT_RValue));
521         std::move(c_obj)(std::move(x));
522         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
523         std::move(c_obj)(std::move(cx));
524         assert(Fn::check_call<const int&&>(CT_Const | CT_RValue));
525         std::move(c_obj)(42);
526         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
527     }
528     { // test multi arg
529         const double y = 3.14;
530         std::string s = "abc";
531         obj(42, std::move(y), s, std::string{"foo"});
532         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue);
533         std::move(obj)(42, std::move(y), s, std::string{"foo"});
534         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue);
535         c_obj(42, std::move(y), s, std::string{"foo"});
536         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_LValue);
537         std::move(c_obj)(42, std::move(y), s, std::string{"foo"});
538         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_RValue);
539     }
540 }
541
542 void call_operator_noexcept_test()
543 {
544     {
545         using T = ConstCallable<bool>;
546         T value(true);
547         auto ret = std::not_fn(value);
548         static_assert(!noexcept(ret()), "call should not be noexcept");
549         auto const& cret = ret;
550         static_assert(!noexcept(cret()), "call should not be noexcept");
551     }
552     {
553         using T = NoExceptCallable<bool>;
554         T value(true);
555         auto ret = std::not_fn(value);
556         LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), "");
557 #if TEST_STD_VER > 14
558         static_assert(noexcept(!std::invoke(value)), "");
559 #endif
560         static_assert(noexcept(ret()), "call should be noexcept");
561         auto const& cret = ret;
562         static_assert(noexcept(cret()), "call should be noexcept");
563     }
564     {
565         using T = NoExceptCallable<NoExceptEvilBool>;
566         T value(true);
567         auto ret = std::not_fn(value);
568         static_assert(noexcept(ret()), "call should not be noexcept");
569         auto const& cret = ret;
570         static_assert(noexcept(cret()), "call should not be noexcept");
571     }
572     {
573         using T = NoExceptCallable<EvilBool>;
574         T value(true);
575         auto ret = std::not_fn(value);
576         static_assert(!noexcept(ret()), "call should not be noexcept");
577         auto const& cret = ret;
578         static_assert(!noexcept(cret()), "call should not be noexcept");
579     }
580 }
581
582 void test_lwg2767() {
583     // See http://wg21.link/LWG2767
584     struct Abstract { virtual void f() const = 0; };
585     struct Derived : public Abstract { void f() const {} };
586     struct F { bool operator()(Abstract&&) { return false; } };
587     {
588         Derived d;
589         Abstract &a = d;
590         bool b = std::not_fn(F{})(std::move(a));
591         assert(b);
592     }
593 }
594
595 int main()
596 {
597     constructor_tests();
598     return_type_tests();
599     other_callable_types_test();
600     throws_in_constructor_test();
601     call_operator_sfinae_test(); // somewhat of an extension
602     call_operator_forwarding_test();
603     call_operator_noexcept_test();
604     test_lwg2767();
605 }