1#include <c10/util/TypeTraits.h>
2#include <gtest/gtest.h>
3
4using namespace c10::guts;
5
6namespace {
7
8namespace test_is_equality_comparable {
9class NotEqualityComparable {};
10class EqualityComparable {};
11
12inline bool operator==(const EqualityComparable&, const EqualityComparable&) {
13 return false;
14}
15
16static_assert(!is_equality_comparable<NotEqualityComparable>::value, "");
17static_assert(is_equality_comparable<EqualityComparable>::value, "");
18static_assert(is_equality_comparable<int>::value, "");
19
20// v_ just exists to silence a compiler warning about
21// operator==(EqualityComparable, EqualityComparable) not being needed
22const bool v_ = EqualityComparable() == EqualityComparable();
23} // namespace test_is_equality_comparable
24
25namespace test_is_hashable {
26class NotHashable {};
27class Hashable {};
28} // namespace test_is_hashable
29} // namespace
30namespace std {
31template <>
32struct hash<test_is_hashable::Hashable> final {
33 size_t operator()(const test_is_hashable::Hashable&) {
34 return 0;
35 }
36};
37} // namespace std
38namespace {
39namespace test_is_hashable {
40static_assert(is_hashable<int>::value, "");
41static_assert(is_hashable<Hashable>::value, "");
42static_assert(!is_hashable<NotHashable>::value, "");
43} // namespace test_is_hashable
44
45namespace test_is_function_type {
46class MyClass {};
47struct Functor {
48 void operator()() {}
49};
50auto lambda = []() {};
51// func() and func__ just exists to silence a compiler warning about lambda
52// being unused
53bool func() {
54 lambda();
55 return true;
56}
57bool func__ = func();
58
59static_assert(is_function_type<void()>::value, "");
60static_assert(is_function_type<int()>::value, "");
61static_assert(is_function_type<MyClass()>::value, "");
62static_assert(is_function_type<void(MyClass)>::value, "");
63static_assert(is_function_type<void(int)>::value, "");
64static_assert(is_function_type<void(void*)>::value, "");
65static_assert(is_function_type<int()>::value, "");
66static_assert(is_function_type<int(MyClass)>::value, "");
67static_assert(is_function_type<int(const MyClass&)>::value, "");
68static_assert(is_function_type<int(MyClass&&)>::value, "");
69static_assert(is_function_type < MyClass && () > ::value, "");
70static_assert(is_function_type < MyClass && (MyClass &&) > ::value, "");
71static_assert(is_function_type<const MyClass&(int, float, MyClass)>::value, "");
72
73static_assert(!is_function_type<void>::value, "");
74static_assert(!is_function_type<int>::value, "");
75static_assert(!is_function_type<MyClass>::value, "");
76static_assert(!is_function_type<void*>::value, "");
77static_assert(!is_function_type<const MyClass&>::value, "");
78static_assert(!is_function_type<MyClass&&>::value, "");
79
80static_assert(
81 !is_function_type<void (*)()>::value,
82 "function pointers aren't plain functions");
83static_assert(
84 !is_function_type<Functor>::value,
85 "Functors aren't plain functions");
86static_assert(
87 !is_function_type<decltype(lambda)>::value,
88 "Lambdas aren't plain functions");
89} // namespace test_is_function_type
90
91namespace test_is_instantiation_of {
92class MyClass {};
93template <class T>
94class Single {};
95template <class T1, class T2>
96class Double {};
97template <class... T>
98class Multiple {};
99
100static_assert(is_instantiation_of<Single, Single<void>>::value, "");
101static_assert(is_instantiation_of<Single, Single<MyClass>>::value, "");
102static_assert(is_instantiation_of<Single, Single<int>>::value, "");
103static_assert(is_instantiation_of<Single, Single<void*>>::value, "");
104static_assert(is_instantiation_of<Single, Single<int*>>::value, "");
105static_assert(is_instantiation_of<Single, Single<const MyClass&>>::value, "");
106static_assert(is_instantiation_of<Single, Single<MyClass&&>>::value, "");
107static_assert(is_instantiation_of<Double, Double<int, void>>::value, "");
108static_assert(
109 is_instantiation_of<Double, Double<const int&, MyClass*>>::value,
110 "");
111static_assert(is_instantiation_of<Multiple, Multiple<>>::value, "");
112static_assert(is_instantiation_of<Multiple, Multiple<int>>::value, "");
113static_assert(
114 is_instantiation_of<Multiple, Multiple<MyClass&, int>>::value,
115 "");
116static_assert(
117 is_instantiation_of<Multiple, Multiple<MyClass&, int, MyClass>>::value,
118 "");
119static_assert(
120 is_instantiation_of<Multiple, Multiple<MyClass&, int, MyClass, void*>>::
121 value,
122 "");
123
124static_assert(!is_instantiation_of<Single, Double<int, int>>::value, "");
125static_assert(!is_instantiation_of<Single, Double<int, void>>::value, "");
126static_assert(!is_instantiation_of<Single, Multiple<int>>::value, "");
127static_assert(!is_instantiation_of<Double, Single<int>>::value, "");
128static_assert(!is_instantiation_of<Double, Multiple<int, int>>::value, "");
129static_assert(!is_instantiation_of<Double, Multiple<>>::value, "");
130static_assert(!is_instantiation_of<Multiple, Double<int, int>>::value, "");
131static_assert(!is_instantiation_of<Multiple, Single<int>>::value, "");
132} // namespace test_is_instantiation_of
133
134namespace test_is_type_condition {
135template <class>
136class NotATypeCondition {};
137static_assert(is_type_condition<std::is_reference>::value, "");
138static_assert(!is_type_condition<NotATypeCondition>::value, "");
139} // namespace test_is_type_condition
140} // namespace
141
142namespace test_lambda_is_stateless {
143template <class Result, class... Args>
144struct MyStatelessFunctor final {
145 Result operator()(Args...) {}
146};
147
148template <class Result, class... Args>
149struct MyStatelessConstFunctor final {
150 Result operator()(Args...) const {}
151};
152
153void 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