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 
92 struct CopyAssignableWrapper {
93   CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
94   CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
95   CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
96   CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
97 
98   template <class ...Args>
99   bool operator()(Args&&...) { return value; }
100 
101   explicit CopyAssignableWrapper(bool x) : value(x) {}
102   bool value;
103 };
104 
105 
106 struct MoveAssignableWrapper {
107   MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
108   MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
109   MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
110   MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
111 
112   template <class ...Args>
113   bool operator()(Args&&...) { return value; }
114 
115   explicit MoveAssignableWrapper(bool x) : value(x) {}
116   bool value;
117 };
118 
119 struct MemFunCallable {
120   explicit MemFunCallable(bool x) : value(x) {}
121 
122   bool return_value() const { return value; }
123   bool return_value_nc() { return value; }
124   bool value;
125 };
126 
127 enum CallType {
128   CT_None,
129   CT_Const,
130   CT_NonConst
131 };
132 
133 struct ForwardingCallObject {
134 
135   template <class ...Args>
136   bool operator()(Args&&... args) & {
137       set_call<Args&&...>(CT_NonConst);
138       return true;
139   }
140 
141   template <class ...Args>
142   bool operator()(Args&&... args) const & {
143       set_call<Args&&...>(CT_Const);
144       return true;
145   }
146 
147   // Don't allow the call operator to be invoked as an rvalue.
148   template <class ...Args>
149   bool operator()(Args&&... args) && = delete;
150 
151   template <class ...Args>
152   bool operator()(Args&&... args) const && = delete;
153 
154   template <class ...Args>
155   static void set_call(CallType type) {
156       assert(last_call_type == CT_None);
157       assert(last_call_args == nullptr);
158       last_call_type = type;
159       last_call_args = &makeArgumentID<Args...>();
160   }
161 
162   template <class ...Args>
163   static bool check_call(CallType type) {
164       bool result =
165            last_call_type == type
166         && last_call_args
167         && *last_call_args == makeArgumentID<Args...>();
168       last_call_type = CT_None;
169       last_call_args = nullptr;
170       return result;
171   }
172 
173   static CallType      last_call_type;
174   static TypeID const* last_call_args;
175 };
176 
177 CallType ForwardingCallObject::last_call_type = CT_None;
178 TypeID const* ForwardingCallObject::last_call_args = nullptr;
179 
180 
181 
182 ///////////////////////////////////////////////////////////////////////////////
183 //                        BOOL TEST TYPES
184 ///////////////////////////////////////////////////////////////////////////////
185 
186 struct EvilBool {
187   static int bang_called;
188 
189   EvilBool(EvilBool const&) = default;
190   EvilBool(EvilBool&&) = default;
191 
192   friend EvilBool operator!(EvilBool const& other) {
193     ++bang_called;
194     return EvilBool{!other.value};
195   }
196 
197 private:
198   friend struct MoveOnlyCallable<EvilBool>;
199   friend struct CopyCallable<EvilBool>;
200   friend struct NoExceptCallable<EvilBool>;
201 
202   explicit EvilBool(bool x) : value(x) {}
203   EvilBool& operator=(EvilBool const& other) = default;
204 
205 public:
206   bool value;
207 };
208 
209 int EvilBool::bang_called = 0;
210 
211 struct ExplicitBool {
212   ExplicitBool(ExplicitBool const&) = default;
213   ExplicitBool(ExplicitBool&&) = default;
214 
215   explicit operator bool() const { return value; }
216 
217 private:
218   friend struct MoveOnlyCallable<ExplicitBool>;
219   friend struct CopyCallable<ExplicitBool>;
220 
221   explicit ExplicitBool(bool x) : value(x) {}
222   ExplicitBool& operator=(bool x) {
223       value = x;
224       return *this;
225   }
226 
227   bool value;
228 };
229 
230 
231 struct NoExceptEvilBool {
232   NoExceptEvilBool(NoExceptEvilBool const&) = default;
233   NoExceptEvilBool(NoExceptEvilBool&&) = default;
234   NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
235 
236   explicit NoExceptEvilBool(bool x) : value(x) {}
237 
238   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
239     return NoExceptEvilBool{!other.value};
240   }
241 
242   bool value;
243 };
244 
245 
246 
247 void constructor_tests()
248 {
249     {
250         using T = MoveOnlyCallable<bool>;
251         T value(true);
252         using RetT = decltype(std::not_fn(std::move(value)));
253         static_assert(std::is_move_constructible<RetT>::value, "");
254         static_assert(!std::is_copy_constructible<RetT>::value, "");
255         static_assert(!std::is_move_assignable<RetT>::value, "");
256         static_assert(!std::is_copy_assignable<RetT>::value, "");
257         auto ret = std::not_fn(std::move(value));
258         // test it was moved from
259         assert(value.value == false);
260         // test that ret() negates the original value 'true'
261         assert(ret() == false);
262         assert(ret(0, 0.0, "blah") == false);
263         // Move ret and test that it was moved from and that ret2 got the
264         // original value.
265         auto ret2 = std::move(ret);
266         assert(ret() == true);
267         assert(ret2() == false);
268         assert(ret2(42) == false);
269     }
270     {
271         using T = CopyCallable<bool>;
272         T value(false);
273         using RetT = decltype(std::not_fn(value));
274         static_assert(std::is_move_constructible<RetT>::value, "");
275         static_assert(std::is_copy_constructible<RetT>::value, "");
276         static_assert(!std::is_move_assignable<RetT>::value, "");
277         static_assert(!std::is_copy_assignable<RetT>::value, "");
278         auto ret = std::not_fn(value);
279         // test that value is unchanged (copied not moved)
280         assert(value.value == false);
281         // test 'ret' has the original value
282         assert(ret() == true);
283         assert(ret(42, 100) == true);
284         // move from 'ret' and check that 'ret2' has the original value.
285         auto ret2 = std::move(ret);
286         assert(ret() == false);
287         assert(ret2() == true);
288         assert(ret2("abc") == true);
289     }
290     {
291         using T = CopyAssignableWrapper;
292         T value(true);
293         T value2(false);
294         using RetT = decltype(std::not_fn(value));
295         static_assert(std::is_move_constructible<RetT>::value, "");
296         static_assert(std::is_copy_constructible<RetT>::value, "");
297         static_assert(std::is_move_assignable<RetT>::value, "");
298         static_assert(std::is_copy_assignable<RetT>::value, "");
299         auto ret = std::not_fn(value);
300         assert(ret() == false);
301         auto ret2 = std::not_fn(value2);
302         assert(ret2() == true);
303         ret = ret2;
304         assert(ret() == true);
305         assert(ret2() == true);
306     }
307     {
308         using T = MoveAssignableWrapper;
309         T value(true);
310         T value2(false);
311         using RetT = decltype(std::not_fn(std::move(value)));
312         static_assert(std::is_move_constructible<RetT>::value, "");
313         static_assert(!std::is_copy_constructible<RetT>::value, "");
314         static_assert(std::is_move_assignable<RetT>::value, "");
315         static_assert(!std::is_copy_assignable<RetT>::value, "");
316         auto ret = std::not_fn(std::move(value));
317         assert(ret() == false);
318         auto ret2 = std::not_fn(std::move(value2));
319         assert(ret2() == true);
320         ret = std::move(ret2);
321         assert(ret() == true);
322     }
323 }
324 
325 void return_type_tests()
326 {
327     using std::is_same;
328     {
329         using T = CopyCallable<bool>;
330         auto ret = std::not_fn(T{false});
331         static_assert(is_same<decltype(ret()), bool>::value, "");
332         static_assert(is_same<decltype(ret("abc")), bool>::value, "");
333         assert(ret() == true);
334     }
335     {
336         using T = CopyCallable<ExplicitBool>;
337         auto ret = std::not_fn(T{true});
338         static_assert(is_same<decltype(ret()), bool>::value, "");
339         static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
340         assert(ret() == false);
341     }
342     {
343         using T = CopyCallable<EvilBool>;
344         auto ret = std::not_fn(T{false});
345         static_assert(is_same<decltype(ret()), EvilBool>::value, "");
346         EvilBool::bang_called = 0;
347         auto value_ret = ret();
348         assert(EvilBool::bang_called == 1);
349         assert(value_ret.value == true);
350         ret();
351         assert(EvilBool::bang_called == 2);
352     }
353 }
354 
355 // Other tests only test using objects with call operators. Test various
356 // other callable types here.
357 void other_callable_types_test()
358 {
359     { // test with function pointer
360         auto ret = std::not_fn(returns_true);
361         assert(ret() == false);
362     }
363     { // test with lambda
364         auto returns_value = [](bool value) { return value; };
365         auto ret = std::not_fn(returns_value);
366         assert(ret(true) == false);
367         assert(ret(false) == true);
368     }
369     { // test with pointer to member function
370         MemFunCallable mt(true);
371         const MemFunCallable mf(false);
372         auto ret = std::not_fn(&MemFunCallable::return_value);
373         assert(ret(mt) == false);
374         assert(ret(mf) == true);
375         assert(ret(&mt) == false);
376         assert(ret(&mf) == true);
377     }
378     { // test with pointer to member function
379         MemFunCallable mt(true);
380         MemFunCallable mf(false);
381         auto ret = std::not_fn(&MemFunCallable::return_value_nc);
382         assert(ret(mt) == false);
383         assert(ret(mf) == true);
384         assert(ret(&mt) == false);
385         assert(ret(&mf) == true);
386     }
387     { // test with pointer to member data
388         MemFunCallable mt(true);
389         const MemFunCallable mf(false);
390         auto ret = std::not_fn(&MemFunCallable::value);
391         assert(ret(mt) == false);
392         assert(ret(mf) == true);
393         assert(ret(&mt) == false);
394         assert(ret(&mf) == true);
395     }
396 }
397 
398 void throws_in_constructor_test()
399 {
400 #ifndef TEST_HAS_NO_EXCEPTIONS
401     struct ThrowsOnCopy {
402       ThrowsOnCopy(ThrowsOnCopy const&) {
403         throw 42;
404       }
405       ThrowsOnCopy() = default;
406       bool operator()() const { assert(false); }
407     };
408     {
409         ThrowsOnCopy cp;
410         try {
411             std::not_fn(cp);
412             assert(false);
413         } catch (int const& value) {
414             assert(value == 42);
415         }
416     }
417 #endif
418 }
419 
420 void call_operator_sfinae_test() {
421     { // wrong number of arguments
422         using T = decltype(std::not_fn(returns_true));
423         static_assert(std::is_callable<T()>::value, ""); // callable only with no args
424         static_assert(!std::is_callable<T(bool)>::value, "");
425     }
426     { // violates const correctness (member function pointer)
427         using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
428         static_assert(std::is_callable<T(MemFunCallable&)>::value, "");
429         static_assert(!std::is_callable<T(const MemFunCallable&)>::value, "");
430     }
431     { // violates const correctness (call object)
432         using Obj = CopyCallable<bool>;
433         using NCT = decltype(std::not_fn(Obj{true}));
434         using CT = const NCT;
435         static_assert(std::is_callable<NCT()>::value, "");
436         static_assert(!std::is_callable<CT()>::value, "");
437     }
438     { // returns bad type with no operator!
439         auto fn = [](auto x) { return x; };
440         using T = decltype(std::not_fn(fn));
441         static_assert(std::is_callable<T(bool)>::value, "");
442         static_assert(!std::is_callable<T(std::string)>::value, "");
443     }
444 }
445 
446 void call_operator_forwarding_test()
447 {
448     using Fn = ForwardingCallObject;
449     auto obj = std::not_fn(Fn{});
450     const auto& c_obj = obj;
451     { // test zero args
452         obj();
453         assert(Fn::check_call<>(CT_NonConst));
454         c_obj();
455         assert(Fn::check_call<>(CT_Const));
456     }
457     { // test value categories
458         int x = 42;
459         const int cx = 42;
460         obj(x);
461         assert(Fn::check_call<int&>(CT_NonConst));
462         obj(cx);
463         assert(Fn::check_call<const int&>(CT_NonConst));
464         obj(std::move(x));
465         assert(Fn::check_call<int&&>(CT_NonConst));
466         obj(std::move(cx));
467         assert(Fn::check_call<const int&&>(CT_NonConst));
468         obj(42);
469         assert(Fn::check_call<int&&>(CT_NonConst));
470     }
471     { // test value categories - const call
472         int x = 42;
473         const int cx = 42;
474         c_obj(x);
475         assert(Fn::check_call<int&>(CT_Const));
476         c_obj(cx);
477         assert(Fn::check_call<const int&>(CT_Const));
478         c_obj(std::move(x));
479         assert(Fn::check_call<int&&>(CT_Const));
480         c_obj(std::move(cx));
481         assert(Fn::check_call<const int&&>(CT_Const));
482         c_obj(42);
483         assert(Fn::check_call<int&&>(CT_Const));
484     }
485     { // test multi arg
486         int x = 42;
487         const double y = 3.14;
488         std::string s = "abc";
489         obj(42, std::move(y), s, std::string{"foo"});
490         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst);
491         c_obj(42, std::move(y), s, std::string{"foo"});
492         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const);
493     }
494     { // call as rvalue test. This should not invoke the functor as an rvalue.
495         std::move(obj)();
496         assert(Fn::check_call<>(CT_NonConst));
497         std::move(c_obj)();
498         assert(Fn::check_call<>(CT_Const));
499     }
500 }
501 
502 void call_operator_noexcept_test()
503 {
504     {
505         using T = ConstCallable<bool>;
506         T value(true);
507         auto ret = std::not_fn(value);
508         static_assert(!noexcept(ret()), "call should not be noexcept");
509         auto const& cret = ret;
510         static_assert(!noexcept(cret()), "call should not be noexcept");
511     }
512     {
513         using T = NoExceptCallable<bool>;
514         T value(true);
515         auto ret = std::not_fn(value);
516         static_assert(noexcept(!_VSTD::__invoke(value)), "");
517         static_assert(noexcept(ret()), "call should be noexcept");
518         auto const& cret = ret;
519         static_assert(noexcept(cret()), "call should be noexcept");
520     }
521     {
522         using T = NoExceptCallable<NoExceptEvilBool>;
523         T value(true);
524         auto ret = std::not_fn(value);
525         static_assert(noexcept(ret()), "call should not be noexcept");
526         auto const& cret = ret;
527         static_assert(noexcept(cret()), "call should not be noexcept");
528     }
529     {
530         using T = NoExceptCallable<EvilBool>;
531         T value(true);
532         auto ret = std::not_fn(value);
533         static_assert(!noexcept(ret()), "call should not be noexcept");
534         auto const& cret = ret;
535         static_assert(!noexcept(cret()), "call should not be noexcept");
536     }
537 }
538 
539 int main()
540 {
541     constructor_tests();
542     return_type_tests();
543     other_callable_types_test();
544     throws_in_constructor_test();
545     call_operator_sfinae_test(); // somewhat of an extension
546     call_operator_forwarding_test();
547     call_operator_noexcept_test();
548 }
549