blob: f6309698250da6624f74e5889e79b0ac96e92802 [file] [log] [blame]
[email protected]a6d6d4682012-06-19 18:34:081// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b38d3572011-02-15 01:27:382// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/template_util.h"
[email protected]a6d6d4682012-06-19 18:34:086
jbroman6bcfec422016-05-26 00:28:467#include <string>
Jan Wilken Dörriea33bc992020-03-24 17:45:318#include <type_traits>
jbroman6bcfec422016-05-26 00:28:469
dyaroshev99a394d2017-07-22 19:10:1810#include "base/containers/flat_tree.h"
11#include "base/test/move_only_int.h"
[email protected]b38d3572011-02-15 01:27:3812#include "testing/gtest/include/gtest/gtest.h"
13
14namespace base {
15namespace {
16
jbroman6bcfec422016-05-26 00:28:4617enum SimpleEnum { SIMPLE_ENUM };
18enum EnumWithExplicitType : uint64_t { ENUM_WITH_EXPLICIT_TYPE };
19enum class ScopedEnum { SCOPED_ENUM };
20enum class ScopedEnumWithOperator { SCOPED_ENUM_WITH_OPERATOR };
21std::ostream& operator<<(std::ostream& os, ScopedEnumWithOperator v) {
22 return os;
23}
24struct SimpleStruct {};
25struct StructWithOperator {};
26std::ostream& operator<<(std::ostream& os, const StructWithOperator& v) {
27 return os;
28}
Collin Baker89e9e072019-06-10 22:39:0529struct StructWithToString {
30 std::string ToString() const { return ""; }
31};
jbroman6bcfec422016-05-26 00:28:4632
[email protected]a6d6d4682012-06-19 18:34:0833// is_non_const_reference<Type>
avi4ec0dff2015-11-24 14:26:2434static_assert(!is_non_const_reference<int>::value, "IsNonConstReference");
35static_assert(!is_non_const_reference<const int&>::value,
36 "IsNonConstReference");
37static_assert(is_non_const_reference<int&>::value, "IsNonConstReference");
[email protected]b38d3572011-02-15 01:27:3838
jbroman6bcfec422016-05-26 00:28:4639// A few standard types that definitely support printing.
40static_assert(internal::SupportsOstreamOperator<int>::value,
41 "ints should be printable");
42static_assert(internal::SupportsOstreamOperator<const char*>::value,
43 "C strings should be printable");
44static_assert(internal::SupportsOstreamOperator<std::string>::value,
45 "std::string should be printable");
46
47// Various kinds of enums operator<< support.
48static_assert(internal::SupportsOstreamOperator<SimpleEnum>::value,
49 "simple enum should be printable by value");
50static_assert(internal::SupportsOstreamOperator<const SimpleEnum&>::value,
51 "simple enum should be printable by const ref");
52static_assert(internal::SupportsOstreamOperator<EnumWithExplicitType>::value,
53 "enum with explicit type should be printable by value");
54static_assert(
55 internal::SupportsOstreamOperator<const EnumWithExplicitType&>::value,
56 "enum with explicit type should be printable by const ref");
57static_assert(!internal::SupportsOstreamOperator<ScopedEnum>::value,
58 "scoped enum should not be printable by value");
59static_assert(!internal::SupportsOstreamOperator<const ScopedEnum&>::value,
60 "simple enum should not be printable by const ref");
61static_assert(internal::SupportsOstreamOperator<ScopedEnumWithOperator>::value,
62 "scoped enum with operator<< should be printable by value");
63static_assert(
64 internal::SupportsOstreamOperator<const ScopedEnumWithOperator&>::value,
65 "scoped enum with operator<< should be printable by const ref");
66
67// operator<< support on structs.
68static_assert(!internal::SupportsOstreamOperator<SimpleStruct>::value,
69 "simple struct should not be printable by value");
70static_assert(!internal::SupportsOstreamOperator<const SimpleStruct&>::value,
71 "simple struct should not be printable by const ref");
72static_assert(internal::SupportsOstreamOperator<StructWithOperator>::value,
73 "struct with operator<< should be printable by value");
74static_assert(
75 internal::SupportsOstreamOperator<const StructWithOperator&>::value,
76 "struct with operator<< should be printable by const ref");
77
Collin Baker89e9e072019-06-10 22:39:0578// .ToString() support on structs.
79static_assert(!internal::SupportsToString<SimpleStruct>::value,
80 "simple struct value doesn't support .ToString()");
81static_assert(!internal::SupportsToString<const SimpleStruct&>::value,
82 "simple struct const ref doesn't support .ToString()");
83static_assert(internal::SupportsToString<StructWithToString>::value,
84 "struct with .ToString() should be printable by value");
85static_assert(internal::SupportsToString<const StructWithToString&>::value,
86 "struct with .ToString() should be printable by const ref");
87
Brett Wilson4208cb52017-07-17 20:52:3088// base::is_trivially_copyable
89class TrivialCopy {
90 public:
91 TrivialCopy(int d) : data_(d) {}
92
93 protected:
94 int data_;
95};
96
97class TrivialCopyButWithDestructor : public TrivialCopy {
98 public:
99 TrivialCopyButWithDestructor(int d) : TrivialCopy(d) {}
100 ~TrivialCopyButWithDestructor() { data_ = 0; }
101};
102
103static_assert(base::is_trivially_copyable<TrivialCopy>::value,
104 "TrivialCopy should be detected as trivially copyable");
105static_assert(!base::is_trivially_copyable<TrivialCopyButWithDestructor>::value,
106 "TrivialCopyButWithDestructor should not be detected as "
107 "trivially copyable");
108
Hidehiko Abe4d8468a2018-02-23 09:50:41109class NoCopy {
110 public:
111 NoCopy(const NoCopy&) = delete;
112};
113
114static_assert(
115 !base::is_trivially_copy_constructible<std::vector<NoCopy>>::value,
116 "is_trivially_copy_constructible<std::vector<T>> must be compiled.");
117
Jan Wilken Dörriea33bc992020-03-24 17:45:31118using TrueT = std::true_type;
119using FalseT = std::false_type;
120
121// bool_constant
122static_assert(std::is_same<TrueT, bool_constant<true>>::value, "");
123static_assert(std::is_same<FalseT, bool_constant<false>>::value, "");
124
125struct True {
126 static constexpr bool value = true;
127};
128
129struct False {
130 static constexpr bool value = false;
131};
132
133// conjunction
134static_assert(conjunction<>::value, "");
135static_assert(conjunction<TrueT>::value, "");
136static_assert(!conjunction<FalseT>::value, "");
137
138static_assert(conjunction<TrueT, TrueT>::value, "");
139static_assert(!conjunction<TrueT, FalseT>::value, "");
140static_assert(!conjunction<FalseT, TrueT>::value, "");
141static_assert(!conjunction<FalseT, FalseT>::value, "");
142
143static_assert(conjunction<TrueT, TrueT, TrueT>::value, "");
144static_assert(!conjunction<TrueT, TrueT, FalseT>::value, "");
145static_assert(!conjunction<TrueT, FalseT, TrueT>::value, "");
146static_assert(!conjunction<TrueT, FalseT, FalseT>::value, "");
147static_assert(!conjunction<FalseT, TrueT, TrueT>::value, "");
148static_assert(!conjunction<FalseT, TrueT, FalseT>::value, "");
149static_assert(!conjunction<FalseT, FalseT, TrueT>::value, "");
150static_assert(!conjunction<FalseT, FalseT, FalseT>::value, "");
151
152static_assert(conjunction<True>::value, "");
153static_assert(!conjunction<False>::value, "");
154
155// disjunction
156static_assert(!disjunction<>::value, "");
157static_assert(disjunction<TrueT>::value, "");
158static_assert(!disjunction<FalseT>::value, "");
159
160static_assert(disjunction<TrueT, TrueT>::value, "");
161static_assert(disjunction<TrueT, FalseT>::value, "");
162static_assert(disjunction<FalseT, TrueT>::value, "");
163static_assert(!disjunction<FalseT, FalseT>::value, "");
164
165static_assert(disjunction<TrueT, TrueT, TrueT>::value, "");
166static_assert(disjunction<TrueT, TrueT, FalseT>::value, "");
167static_assert(disjunction<TrueT, FalseT, TrueT>::value, "");
168static_assert(disjunction<TrueT, FalseT, FalseT>::value, "");
169static_assert(disjunction<FalseT, TrueT, TrueT>::value, "");
170static_assert(disjunction<FalseT, TrueT, FalseT>::value, "");
171static_assert(disjunction<FalseT, FalseT, TrueT>::value, "");
172static_assert(!disjunction<FalseT, FalseT, FalseT>::value, "");
173
174static_assert(disjunction<True>::value, "");
175static_assert(!disjunction<False>::value, "");
176
177// negation
178static_assert(!negation<TrueT>::value, "");
179static_assert(negation<FalseT>::value, "");
180
181static_assert(!negation<True>::value, "");
182static_assert(negation<False>::value, "");
183
184static_assert(negation<negation<TrueT>>::value, "");
185static_assert(!negation<negation<FalseT>>::value, "");
186
Jan Wilken Dörriec61b66442021-03-02 13:16:48187// is_invocable
188TEST(TemplateUtil, IsInvocable) {
189 struct Base {};
190 struct Derived : Base {};
191
192 struct Implicit {
193 Implicit(int) {}
194 };
195
196 struct Explicit {
197 explicit Explicit(int) {}
198 };
199
200 struct CallableWithBaseButNotWithInt {
201 int operator()(int) = delete;
202 int operator()(Base) { return 42; }
203 };
204
205 {
206 using Fp = void (*)(Base&, int);
207 static_assert(is_invocable<Fp, Base&, int>::value, "");
208 static_assert(is_invocable<Fp, Derived&, int>::value, "");
209 static_assert(!is_invocable<Fp, const Base&, int>::value, "");
210 static_assert(!is_invocable<Fp>::value, "");
211 static_assert(!is_invocable<Fp, Base&>::value, "");
212 }
213 {
214 // Function reference
215 using Fp = void (&)(Base&, int);
216 static_assert(is_invocable<Fp, Base&, int>::value, "");
217 static_assert(is_invocable<Fp, Derived&, int>::value, "");
218 static_assert(!is_invocable<Fp, const Base&, int>::value, "");
219 static_assert(!is_invocable<Fp>::value, "");
220 static_assert(!is_invocable<Fp, Base&>::value, "");
221 }
222 {
223 // Function object
224 using Fn = CallableWithBaseButNotWithInt;
225 static_assert(is_invocable<Fn, Base>::value, "");
226 static_assert(!is_invocable<Fn, int>::value, "");
227 }
228 {
229 // Check that the conversion to the return type is properly checked
230 using Fn = int (*)(int);
231 static_assert(is_invocable_r<Implicit, Fn, int>::value, "");
232 static_assert(is_invocable_r<double, Fn, int>::value, "");
233 static_assert(is_invocable_r<const volatile void, Fn, int>::value, "");
234 static_assert(!is_invocable_r<Explicit, Fn, int>::value, "");
235
236 static_assert(is_invocable_r<Implicit, Fn, double>::value, "");
237 static_assert(!is_invocable_r<double, Fn, std::string>::value, "");
238 static_assert(is_invocable_r<const volatile void, Fn, double>::value, "");
239 static_assert(!is_invocable_r<Explicit, Fn, double>::value, "");
240 }
241}
242
Jan Wilken Dörrief89fc2ac2021-03-05 06:51:22243// is_scoped_enum
244TEST(TemplateUtil, IsScopedEnum) {
245 static_assert(!is_scoped_enum<int>::value, "");
246 static_assert(!is_scoped_enum<SimpleEnum>::value, "");
247 static_assert(!is_scoped_enum<EnumWithExplicitType>::value, "");
248 static_assert(is_scoped_enum<ScopedEnum>::value, "");
249}
250
Jan Wilken Dörrie94bb5bc2021-03-22 18:37:40251TEST(TemplateUtil, RemoveCvRefT) {
252 static_assert(std::is_same<int, remove_cvref_t<const int>>::value, "");
253 static_assert(std::is_same<int, remove_cvref_t<const volatile int>>::value,
254 "");
255 static_assert(std::is_same<int, remove_cvref_t<int&>>::value, "");
256 static_assert(std::is_same<int, remove_cvref_t<const int&>>::value, "");
257 static_assert(std::is_same<int, remove_cvref_t<const volatile int&>>::value,
258 "");
259 static_assert(std::is_same<int, remove_cvref_t<int&&>>::value, "");
260 static_assert(
261 std::is_same<SimpleStruct, remove_cvref_t<const SimpleStruct&>>::value,
262 "");
263 static_assert(std::is_same<int*, remove_cvref_t<int*>>::value, "");
264
265 // Test references and pointers to arrays.
266 static_assert(std::is_same<int[3], remove_cvref_t<int[3]>>::value, "");
267 static_assert(std::is_same<int[3], remove_cvref_t<int(&)[3]>>::value, "");
268 static_assert(std::is_same<int(*)[3], remove_cvref_t<int(*)[3]>>::value, "");
269
270 // Test references and pointers to functions.
271 static_assert(std::is_same<void(int), remove_cvref_t<void(int)>>::value, "");
272 static_assert(std::is_same<void(int), remove_cvref_t<void (&)(int)>>::value,
273 "");
274 static_assert(
275 std::is_same<void (*)(int), remove_cvref_t<void (*)(int)>>::value, "");
276}
277
[email protected]b38d3572011-02-15 01:27:38278} // namespace
dyaroshev99a394d2017-07-22 19:10:18279
[email protected]b38d3572011-02-15 01:27:38280} // namespace base