1 | #include <c10/util/TypeTraits.h> |
2 | #include <gtest/gtest.h> |
3 | |
4 | using namespace c10::guts; |
5 | |
6 | namespace { |
7 | |
8 | namespace test_is_equality_comparable { |
9 | class NotEqualityComparable {}; |
10 | class EqualityComparable {}; |
11 | |
12 | inline bool operator==(const EqualityComparable&, const EqualityComparable&) { |
13 | return false; |
14 | } |
15 | |
16 | static_assert(!is_equality_comparable<NotEqualityComparable>::value, "" ); |
17 | static_assert(is_equality_comparable<EqualityComparable>::value, "" ); |
18 | static_assert(is_equality_comparable<int>::value, "" ); |
19 | |
20 | // v_ just exists to silence a compiler warning about |
21 | // operator==(EqualityComparable, EqualityComparable) not being needed |
22 | const bool v_ = EqualityComparable() == EqualityComparable(); |
23 | } // namespace test_is_equality_comparable |
24 | |
25 | namespace test_is_hashable { |
26 | class NotHashable {}; |
27 | class Hashable {}; |
28 | } // namespace test_is_hashable |
29 | } // namespace |
30 | namespace std { |
31 | template <> |
32 | struct hash<test_is_hashable::Hashable> final { |
33 | size_t operator()(const test_is_hashable::Hashable&) { |
34 | return 0; |
35 | } |
36 | }; |
37 | } // namespace std |
38 | namespace { |
39 | namespace test_is_hashable { |
40 | static_assert(is_hashable<int>::value, "" ); |
41 | static_assert(is_hashable<Hashable>::value, "" ); |
42 | static_assert(!is_hashable<NotHashable>::value, "" ); |
43 | } // namespace test_is_hashable |
44 | |
45 | namespace test_is_function_type { |
46 | class MyClass {}; |
47 | struct Functor { |
48 | void operator()() {} |
49 | }; |
50 | auto lambda = []() {}; |
51 | // func() and func__ just exists to silence a compiler warning about lambda |
52 | // being unused |
53 | bool func() { |
54 | lambda(); |
55 | return true; |
56 | } |
57 | bool func__ = func(); |
58 | |
59 | static_assert(is_function_type<void()>::value, "" ); |
60 | static_assert(is_function_type<int()>::value, "" ); |
61 | static_assert(is_function_type<MyClass()>::value, "" ); |
62 | static_assert(is_function_type<void(MyClass)>::value, "" ); |
63 | static_assert(is_function_type<void(int)>::value, "" ); |
64 | static_assert(is_function_type<void(void*)>::value, "" ); |
65 | static_assert(is_function_type<int()>::value, "" ); |
66 | static_assert(is_function_type<int(MyClass)>::value, "" ); |
67 | static_assert(is_function_type<int(const MyClass&)>::value, "" ); |
68 | static_assert(is_function_type<int(MyClass&&)>::value, "" ); |
69 | static_assert(is_function_type < MyClass && () > ::value, "" ); |
70 | static_assert(is_function_type < MyClass && (MyClass &&) > ::value, "" ); |
71 | static_assert(is_function_type<const MyClass&(int, float, MyClass)>::value, "" ); |
72 | |
73 | static_assert(!is_function_type<void>::value, "" ); |
74 | static_assert(!is_function_type<int>::value, "" ); |
75 | static_assert(!is_function_type<MyClass>::value, "" ); |
76 | static_assert(!is_function_type<void*>::value, "" ); |
77 | static_assert(!is_function_type<const MyClass&>::value, "" ); |
78 | static_assert(!is_function_type<MyClass&&>::value, "" ); |
79 | |
80 | static_assert( |
81 | !is_function_type<void (*)()>::value, |
82 | "function pointers aren't plain functions" ); |
83 | static_assert( |
84 | !is_function_type<Functor>::value, |
85 | "Functors aren't plain functions" ); |
86 | static_assert( |
87 | !is_function_type<decltype(lambda)>::value, |
88 | "Lambdas aren't plain functions" ); |
89 | } // namespace test_is_function_type |
90 | |
91 | namespace test_is_instantiation_of { |
92 | class MyClass {}; |
93 | template <class T> |
94 | class Single {}; |
95 | template <class T1, class T2> |
96 | class Double {}; |
97 | template <class... T> |
98 | class Multiple {}; |
99 | |
100 | static_assert(is_instantiation_of<Single, Single<void>>::value, "" ); |
101 | static_assert(is_instantiation_of<Single, Single<MyClass>>::value, "" ); |
102 | static_assert(is_instantiation_of<Single, Single<int>>::value, "" ); |
103 | static_assert(is_instantiation_of<Single, Single<void*>>::value, "" ); |
104 | static_assert(is_instantiation_of<Single, Single<int*>>::value, "" ); |
105 | static_assert(is_instantiation_of<Single, Single<const MyClass&>>::value, "" ); |
106 | static_assert(is_instantiation_of<Single, Single<MyClass&&>>::value, "" ); |
107 | static_assert(is_instantiation_of<Double, Double<int, void>>::value, "" ); |
108 | static_assert( |
109 | is_instantiation_of<Double, Double<const int&, MyClass*>>::value, |
110 | "" ); |
111 | static_assert(is_instantiation_of<Multiple, Multiple<>>::value, "" ); |
112 | static_assert(is_instantiation_of<Multiple, Multiple<int>>::value, "" ); |
113 | static_assert( |
114 | is_instantiation_of<Multiple, Multiple<MyClass&, int>>::value, |
115 | "" ); |
116 | static_assert( |
117 | is_instantiation_of<Multiple, Multiple<MyClass&, int, MyClass>>::value, |
118 | "" ); |
119 | static_assert( |
120 | is_instantiation_of<Multiple, Multiple<MyClass&, int, MyClass, void*>>:: |
121 | value, |
122 | "" ); |
123 | |
124 | static_assert(!is_instantiation_of<Single, Double<int, int>>::value, "" ); |
125 | static_assert(!is_instantiation_of<Single, Double<int, void>>::value, "" ); |
126 | static_assert(!is_instantiation_of<Single, Multiple<int>>::value, "" ); |
127 | static_assert(!is_instantiation_of<Double, Single<int>>::value, "" ); |
128 | static_assert(!is_instantiation_of<Double, Multiple<int, int>>::value, "" ); |
129 | static_assert(!is_instantiation_of<Double, Multiple<>>::value, "" ); |
130 | static_assert(!is_instantiation_of<Multiple, Double<int, int>>::value, "" ); |
131 | static_assert(!is_instantiation_of<Multiple, Single<int>>::value, "" ); |
132 | } // namespace test_is_instantiation_of |
133 | |
134 | namespace test_is_type_condition { |
135 | template <class> |
136 | class NotATypeCondition {}; |
137 | static_assert(is_type_condition<std::is_reference>::value, "" ); |
138 | static_assert(!is_type_condition<NotATypeCondition>::value, "" ); |
139 | } // namespace test_is_type_condition |
140 | } // namespace |
141 | |
142 | namespace test_lambda_is_stateless { |
143 | template <class Result, class... Args> |
144 | struct MyStatelessFunctor final { |
145 | Result operator()(Args...) {} |
146 | }; |
147 | |
148 | template <class Result, class... Args> |
149 | struct MyStatelessConstFunctor final { |
150 | Result operator()(Args...) const {} |
151 | }; |
152 | |
153 | void func() { |
154 | auto stateless_lambda = [](int a) { return a; }; |
155 | static_assert(is_stateless_lambda<decltype(stateless_lambda)>::value, "" ); |
156 | |
157 | int b = 4; |
158 | auto stateful_lambda_1 = [&](int a) { return a + b; }; |
159 | static_assert(!is_stateless_lambda<decltype(stateful_lambda_1)>::value, "" ); |
160 | |
161 | auto stateful_lambda_2 = [=](int a) { return a + b; }; |
162 | static_assert(!is_stateless_lambda<decltype(stateful_lambda_2)>::value, "" ); |
163 | |
164 | auto stateful_lambda_3 = [b](int a) { return a + b; }; |
165 | static_assert(!is_stateless_lambda<decltype(stateful_lambda_3)>::value, "" ); |
166 | |
167 | static_assert( |
168 | !is_stateless_lambda<MyStatelessFunctor<int, int>>::value, |
169 | "even if stateless, a functor is not a lambda, so it's false" ); |
170 | static_assert( |
171 | !is_stateless_lambda<MyStatelessFunctor<void, int>>::value, |
172 | "even if stateless, a functor is not a lambda, so it's false" ); |
173 | static_assert( |
174 | !is_stateless_lambda<MyStatelessConstFunctor<int, int>>::value, |
175 | "even if stateless, a functor is not a lambda, so it's false" ); |
176 | static_assert( |
177 | !is_stateless_lambda<MyStatelessConstFunctor<void, int>>::value, |
178 | "even if stateless, a functor is not a lambda, so it's false" ); |
179 | |
180 | class Dummy final {}; |
181 | static_assert( |
182 | !is_stateless_lambda<Dummy>::value, |
183 | "A non-functor type is also not a lambda" ); |
184 | |
185 | static_assert(!is_stateless_lambda<int>::value, "An int is not a lambda" ); |
186 | |
187 | using Func = int(int); |
188 | static_assert( |
189 | !is_stateless_lambda<Func>::value, "A function is not a lambda" ); |
190 | static_assert( |
191 | !is_stateless_lambda<Func*>::value, "A function pointer is not a lambda" ); |
192 | } |
193 | } // namespace test_lambda_is_stateless |
194 | |