xref: /llvm-project/libcxx/test/support/callable_types.h (revision c2df70766647b39d302ab5ab952980e0b3b4d725)
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 #ifndef TEST_CALLABLE_TYPES_H
10 #define TEST_CALLABLE_TYPES_H
11 
12 #include "test_macros.h"
13 #include "type_id.h"
14 
15 ///////////////////////////////////////////////////////////////////////////////
16 //                       CALLABLE TEST TYPES
17 ///////////////////////////////////////////////////////////////////////////////
18 
returns_true()19 constexpr bool returns_true() { return true; }
20 
21 template <class Ret>
22 struct MoveOnlyCallable {
23   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
MoveOnlyCallableMoveOnlyCallable24   constexpr MoveOnlyCallable(MoveOnlyCallable&& other)
25       : value(other.value)
26   { other.value = !other.value; }
27 
28   template <class ...Args>
operatorMoveOnlyCallable29   constexpr Ret operator()(Args&&...) { return Ret{value}; }
30 
MoveOnlyCallableMoveOnlyCallable31   constexpr explicit MoveOnlyCallable(bool x) : value(x) {}
32   Ret value;
33 };
34 
35 template <class Ret>
36 struct CopyCallable {
CopyCallableCopyCallable37   constexpr CopyCallable(CopyCallable const& other)
38       : value(other.value) {}
39 
CopyCallableCopyCallable40   constexpr CopyCallable(CopyCallable&& other)
41       : value(other.value) { other.value = !other.value; }
42 
43   template <class ...Args>
operatorCopyCallable44   constexpr Ret operator()(Args&&...) { return Ret{value}; }
45 
CopyCallableCopyCallable46   constexpr explicit CopyCallable(bool x) : value(x)  {}
47   Ret value;
48 };
49 
50 
51 template <class Ret>
52 struct ConstCallable {
ConstCallableConstCallable53   constexpr ConstCallable(ConstCallable const& other)
54       : value(other.value) {}
55 
ConstCallableConstCallable56   constexpr ConstCallable(ConstCallable&& other)
57       : value(other.value) { other.value = !other.value; }
58 
59   template <class ...Args>
operatorConstCallable60   constexpr Ret operator()(Args&&...) const { return Ret{value}; }
61 
ConstCallableConstCallable62   constexpr explicit ConstCallable(bool x) : value(x)  {}
63   Ret value;
64 };
65 
66 
67 
68 template <class Ret>
69 struct NoExceptCallable {
NoExceptCallableNoExceptCallable70   constexpr NoExceptCallable(NoExceptCallable const& other)
71       : value(other.value) {}
72 
73   template <class ...Args>
operatorNoExceptCallable74   constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; }
75 
76   template <class ...Args>
operatorNoExceptCallable77   constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; }
78 
NoExceptCallableNoExceptCallable79   constexpr explicit NoExceptCallable(bool x) : value(x)  {}
80   Ret value;
81 };
82 
83 struct CopyAssignableWrapper {
84   constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
85   constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
86   constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
87   constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
88 
89   template <class ...Args>
operatorCopyAssignableWrapper90   constexpr bool operator()(Args&&...) { return value; }
91 
CopyAssignableWrapperCopyAssignableWrapper92   constexpr explicit CopyAssignableWrapper(bool x) : value(x) {}
93   bool value;
94 };
95 
96 
97 struct MoveAssignableWrapper {
98   constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
99   constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
100   constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
101   constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
102 
103   template <class ...Args>
operatorMoveAssignableWrapper104   constexpr bool operator()(Args&&...) { return value; }
105 
MoveAssignableWrapperMoveAssignableWrapper106   constexpr explicit MoveAssignableWrapper(bool x) : value(x) {}
107   bool value;
108 };
109 
110 struct MemFunCallable {
MemFunCallableMemFunCallable111   constexpr explicit MemFunCallable(bool x) : value(x) {}
112 
return_valueMemFunCallable113   constexpr bool return_value() const { return value; }
return_value_ncMemFunCallable114   constexpr bool return_value_nc() { return value; }
115   bool value;
116 };
117 
118 enum CallType : unsigned {
119   CT_None,
120   CT_NonConst = 1,
121   CT_Const = 2,
122   CT_LValue = 4,
123   CT_RValue = 8
124 };
125 
126 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
127     return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
128 }
129 
130 struct ForwardingCallObject {
131   struct State {
132     CallType      last_call_type = CT_None;
133     TypeID const& (*last_call_args)() = nullptr;
134 
135     template <class ...Args>
set_callForwardingCallObject::State136     constexpr void set_call(CallType type) {
137       assert(last_call_type == CT_None);
138       assert(last_call_args == nullptr);
139       last_call_type = type;
140       last_call_args = &makeArgumentID<Args...>;
141     }
142 
143     template <class ...Args>
check_callForwardingCallObject::State144     constexpr bool check_call(CallType type) {
145       bool result =
146            last_call_type == type
147         && last_call_args
148         && *last_call_args == &makeArgumentID<Args...>;
149       last_call_type = CT_None;
150       last_call_args = nullptr;
151       return result;
152     }
153   };
154 
155   State *st_;
156 
ForwardingCallObjectForwardingCallObject157   explicit constexpr ForwardingCallObject(State& st) : st_(&st) {}
158 
159   template <class ...Args>
operatorForwardingCallObject160   constexpr bool operator()(Args&&...) & {
161       st_->set_call<Args&&...>(CT_NonConst | CT_LValue);
162       return true;
163   }
164 
165   template <class ...Args>
operatorForwardingCallObject166   constexpr bool operator()(Args&&...) const & {
167       st_->set_call<Args&&...>(CT_Const | CT_LValue);
168       return true;
169   }
170 
171   // Don't allow the call operator to be invoked as an rvalue.
172   template <class ...Args>
operatorForwardingCallObject173   constexpr bool operator()(Args&&...) && {
174       st_->set_call<Args&&...>(CT_NonConst | CT_RValue);
175       return true;
176   }
177 
178   template <class ...Args>
operatorForwardingCallObject179   constexpr bool operator()(Args&&...) const && {
180       st_->set_call<Args&&...>(CT_Const | CT_RValue);
181       return true;
182   }
183 };
184 
185 
186 #endif // TEST_CALLABLE_TYPES_H
187