type_list_utilities.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2023, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "cudf_gtest.hpp"
19 
71 namespace cudf {
72 namespace test {
73 // Utilities for creating parameters for typed tests on GoogleTest
74 //
75 // Types is used to define type list, it's just an alias to ::testing::Types:
76 // using Types = util::Types<int,char,float>;
77 //
78 
79 // Types -----------------------------------------
80 using ::testing::Types;
81 
82 // @cond
83 template <class T, int D>
84 struct GetTypeImpl {
85  static_assert(D == 0, "Out of bounds");
86  using type = T;
87 };
88 
89 template <class... T, int D>
90 struct GetTypeImpl<Types<T...>, D> {
91  static_assert(D < sizeof...(T), "Out of bounds");
92 
93  using raw_type = decltype(std::get<D>(std::declval<std::tuple<T...>>()));
94  using type = std::decay_t<raw_type>;
95 };
96 template <class T, class... ARGS>
97 struct GetTypeImpl<Types<T, ARGS...>, 0> {
98  using type = T;
99 };
100 // @endcond
101 
114 template <class TUPLE, int D>
115 using GetType = typename GetTypeImpl<TUPLE, D>::type;
116 
117 // GetSize -------------------------------
118 // @cond
119 template <class TUPLE>
120 struct GetSizeImpl;
121 
122 template <class... TYPES>
123 struct GetSizeImpl<Types<TYPES...>> {
124  static constexpr auto value = sizeof...(TYPES);
125 };
126 // @endcond
127 
136 template <class TUPLE>
137 constexpr auto GetSize = GetSizeImpl<TUPLE>::value;
138 
139 // Concat -----------------------------------------
140 // @cond
141 namespace detail {
142 template <class A, class B>
143 struct Concat2;
144 
145 template <class... T, class... U>
146 struct Concat2<Types<T...>, Types<U...>> {
147  using type = Types<T..., U...>;
148 };
149 } // namespace detail
150 
151 template <class... T>
152 struct ConcatImpl;
153 
154 template <class HEAD1, class HEAD2, class... TAIL>
155 struct ConcatImpl<HEAD1, HEAD2, TAIL...> {
156  using type = typename ConcatImpl<typename detail::Concat2<HEAD1, HEAD2>::type, TAIL...>::type;
157 };
158 
159 template <class A>
160 struct ConcatImpl<A> {
161  using type = A;
162 };
163 
164 template <class... A>
165 struct ConcatImpl<Types<A...>> {
166  using type = Types<A...>;
167 };
168 
169 template <>
170 struct ConcatImpl<> {
171  using type = Types<>;
172 };
173 // @endcond
174 
184 template <class... T>
185 using Concat = typename ConcatImpl<T...>::type;
186 
187 // Flatten -----------------------------------------
188 // @cond
189 template <class T>
190 struct FlattenImpl;
191 
192 template <>
193 struct FlattenImpl<Types<>> {
194  using type = Types<>;
195 };
196 
197 template <class HEAD, class... TAIL>
198 struct FlattenImpl<Types<HEAD, TAIL...>> {
199  using type = Concat<Types<HEAD>, typename FlattenImpl<Types<TAIL...>>::type>;
200 };
201 
202 template <class... HEAD, class... TAIL>
203 struct FlattenImpl<Types<Types<HEAD...>, TAIL...>> {
204  using type = typename FlattenImpl<Types<HEAD..., TAIL...>>::type;
205 };
206 // @endcond
207 
219 template <class T>
220 using Flatten = typename FlattenImpl<T>::type;
221 
222 // CrossProduct -----------------------------------------
223 // @cond
224 namespace detail {
225 // prepend T in TUPLE
226 template <class T, class TUPLE>
227 struct Prepend1;
228 
229 template <class T, class... ARGS>
230 struct Prepend1<T, Types<ARGS...>> {
231  using type = Flatten<Types<T, ARGS...>>;
232 };
233 
234 template <class T, class TUPLES>
235 struct Prepend;
236 
237 // Prepend T in all TUPLES
238 template <class T, class... TUPLES>
239 struct Prepend<T, Types<TUPLES...>> {
240  using type = Types<typename Prepend1<T, TUPLES>::type...>;
241 };
242 
243 // skip empty tuples
244 template <class T, class... TUPLES>
245 struct Prepend<T, Types<Types<>, TUPLES...>> : Prepend<T, Types<TUPLES...>> {};
246 } // namespace detail
247 
248 template <class... ARGS>
249 struct CrossProductImpl;
250 
251 template <>
252 struct CrossProductImpl<> {
253  using type = Types<>;
254 };
255 
256 template <class... ARGS>
257 struct CrossProductImpl<Types<ARGS...>> {
258  using type = Types<Types<ARGS>...>;
259 };
260 
261 template <class... AARGS, class... TAIL>
262 struct CrossProductImpl<Types<AARGS...>, TAIL...> {
263  using type =
264  Concat<typename detail::Prepend<AARGS, typename CrossProductImpl<TAIL...>::type>::type...>;
265 };
266 
267 // to make it easy for the user when there's only one element to be joined
268 template <class T, class... TAIL>
269 struct CrossProductImpl<T, TAIL...> : CrossProductImpl<Types<T>, TAIL...> {};
270 // @endcond
271 
287 template <class... ARGS>
288 using CrossProduct = typename CrossProductImpl<ARGS...>::type;
289 
290 // AllSame -----------------------------------------
291 // @cond
292 namespace detail {
293 template <class... ITEMS>
294 struct AllSame : std::false_type {};
295 
296 // degenerate case
297 template <class A>
298 struct AllSame<A> : std::true_type {};
299 
300 template <class A>
301 struct AllSame<A, A> : std::true_type {};
302 
303 template <class HEAD, class... TAIL>
304 struct AllSame<HEAD, HEAD, TAIL...> : AllSame<HEAD, TAIL...> {};
305 
306 template <class... ITEMS>
307 struct AllSame<Types<ITEMS...>> : AllSame<ITEMS...> {};
308 
309 } // namespace detail
310 // @endcond
311 
328 struct AllSame {
334  template <class... ITEMS>
335  using Call = detail::AllSame<ITEMS...>;
336 };
337 
338 // Exists ---------------------------------
339 // @cond
340 // Do a linear search to find NEEDLE in HAYSACK
341 template <class NEEDLE, class HAYSACK>
342 struct ExistsImpl;
343 
344 // end case, no more types to check
345 template <class NEEDLE>
346 struct ExistsImpl<NEEDLE, Types<>> : std::false_type {};
347 
348 // next one matches
349 template <class NEEDLE, class... TAIL>
350 struct ExistsImpl<NEEDLE, Types<NEEDLE, TAIL...>> : std::true_type {};
351 
352 // next one doesn't match
353 template <class NEEDLE, class HEAD, class... TAIL>
354 struct ExistsImpl<NEEDLE, Types<HEAD, TAIL...>> : ExistsImpl<NEEDLE, Types<TAIL...>> {};
355 // @endcond
356 
368 template <class NEEDLE, class HAYSACK>
369 constexpr bool Exists = ExistsImpl<NEEDLE, HAYSACK>::value;
370 
371 // ContainedIn -----------------------------------------
392 template <class HAYSACK>
393 struct ContainedIn {
399  template <class NEEDLE>
400  using Call = ExistsImpl<NEEDLE, HAYSACK>;
401 };
402 
403 // RemoveIf -----------------------------------------
404 // @cond
405 template <class PRED, class TUPLE>
406 struct RemoveIfImpl;
407 
408 template <class PRED>
409 struct RemoveIfImpl<PRED, Types<>> {
410  using type = Types<>;
411 };
412 
413 template <class PRED, class HEAD, class... TAIL>
414 struct RemoveIfImpl<PRED, Types<HEAD, TAIL...>> {
415  using type =
416  Concat<typename std::conditional<PRED::template Call<HEAD>::value, Types<>, Types<HEAD>>::type,
417  typename RemoveIfImpl<PRED, Types<TAIL...>>::type>;
418 };
419 // @endcond
420 
440 template <class PRED, class TUPLE>
441 using RemoveIf = typename RemoveIfImpl<PRED, TUPLE>::type;
442 
443 // Transform --------------------------------
444 // @cond
445 template <class XFORM, class TYPES>
446 struct TransformImpl;
447 
448 template <class XFORM, class... ITEMS>
449 struct TransformImpl<XFORM, Types<ITEMS...>> {
450  using type = Types<typename XFORM::template Call<ITEMS>...>;
451 };
452 // @endcond
453 
469 template <class XFORM, class TYPES>
470 using Transform = typename TransformImpl<XFORM, TYPES>::type;
471 
472 // Repeat --------------------------------
473 // @cond
474 namespace detail {
475 template <class T, int N, class RES>
476 struct Repeat;
477 
478 template <class T, int N, class... ITEMS>
479 struct Repeat<T, N, Types<ITEMS...>> {
480  using type = typename Repeat<T, N - 1, Types<T, ITEMS...>>::type;
481 };
482 
483 template <class T, class... ITEMS>
484 struct Repeat<T, 0, Types<ITEMS...>> {
485  using type = Types<ITEMS...>;
486 };
487 } // namespace detail
488 // @endcond
489 
504 template <int N>
505 struct Repeat {
511  template <class T>
512  using Call = typename detail::Repeat<T, N, Types<>>::type;
513 };
514 
515 // Append --------------------------------
516 // @cond
517 template <class TYPES, class... ITEMS>
518 struct AppendImpl;
519 
520 template <class... HEAD, class... TAIL>
521 struct AppendImpl<Types<HEAD...>, TAIL...> {
522  using type = Types<HEAD..., TAIL...>;
523 };
524 // @endcond
525 
538 template <class TYPES, class... ITEMS>
539 using Append = typename AppendImpl<TYPES, ITEMS...>::type;
540 
541 // Remove -------------------------------------------
542 // remove items from tuple given by their indices
543 // @cond
544 namespace detail {
545 template <class TUPLE, int CUR, int... IDXs>
546 struct Remove;
547 
548 // nothing else to do?
549 template <class... ITEMS, int CUR>
550 struct Remove<Types<ITEMS...>, CUR> {
551  using type = Types<ITEMS...>;
552 };
553 
554 // index match current item?
555 template <class HEAD, class... TAIL, int CUR, int... IDXTAIL>
556 struct Remove<Types<HEAD, TAIL...>, CUR, CUR, IDXTAIL...> {
557  // remove it, and recurse into the remaining items
558  using type = typename Remove<Types<TAIL...>, CUR + 1, IDXTAIL...>::type;
559 };
560 
561 // index doesn't match current item?
562 template <class HEAD, class... TAIL, int CUR, int IDXHEAD, int... IDXTAIL>
563 struct Remove<Types<HEAD, TAIL...>, CUR, IDXHEAD, IDXTAIL...> {
564  static_assert(sizeof...(TAIL) + 1 > IDXHEAD - CUR, "Index out of bounds");
565 
566  // add current item to output and recurse into the remaining items
567  using type =
568  Concat<Types<HEAD>, typename Remove<Types<TAIL...>, CUR + 1, IDXHEAD, IDXTAIL...>::type>;
569 };
570 } // namespace detail
571 
572 template <class TUPLE, int... IDXs>
573 struct RemoveImpl {
574  using type = typename detail::Remove<TUPLE, 0, IDXs...>::type;
575 };
576 // @endcond
577 
584 template <class TUPLE, int... IDXs>
585 using Remove = typename RemoveImpl<TUPLE, IDXs...>::type;
586 
587 // Unique --------------------------------
588 // @cond
589 namespace detail {
590 template <class... ITEMS>
591 struct Unique;
592 
593 template <>
594 struct Unique<> {
595  using type = Types<>;
596 };
597 
598 template <class HEAD, class... TAIL>
599 struct Unique<HEAD, TAIL...> {
600  using type = Concat<std::conditional_t<Exists<HEAD, Types<TAIL...>>, Types<>, Types<HEAD>>,
601  typename Unique<TAIL...>::type>;
602 };
603 } // namespace detail
604 
605 template <class TYPES>
606 struct UniqueImpl;
607 
608 template <class... ITEMS>
609 struct UniqueImpl<Types<ITEMS...>> {
610  using type = typename detail::Unique<ITEMS...>::type;
611 };
612 // @endcond
613 
625 template <class TYPES>
626 using Unique = typename UniqueImpl<TYPES>::type;
627 
628 } // namespace test
629 
630 } // namespace cudf
cuDF interfaces
Definition: aggregation.hpp:34
Indicates if all types in a list are identical.
detail::AllSame< ITEMS... > Call
Invoked as predicate for RemoveIf.
Indicates if a type exists within a type list.
ExistsImpl< NEEDLE, HAYSACK > Call
Invoked as predicate for RemoveIf.
Transformation that repeats a type for a specified count.
typename detail::Repeat< T, N, Types<> >::type Call
Invoked as predicate for Transform.
typename FlattenImpl< T >::type Flatten
Flattens nested compile-time lists of types into a single list of types.
constexpr bool Exists
Indicates if a type exists within a type list.
typename ConcatImpl< T... >::type Concat
Concatenates compile-time lists of types into a single type list.
typename RemoveIfImpl< PRED, TUPLE >::type RemoveIf
Removes types from a type list that satisfy a predicate.
typename CrossProductImpl< ARGS... >::type CrossProduct
Creates a new type list from the cross product (cartesian product) of two type lists.
typename RemoveImpl< TUPLE, IDXs... >::type Remove
Removes types at specified indices from a type list.
constexpr auto GetSize
Returns the size (number of elements) in a type list.
typename AppendImpl< TYPES, ITEMS... >::type Append
Appends types to a type list.
typename UniqueImpl< TYPES >::type Unique
Removes duplicate types from a type list.
typename TransformImpl< XFORM, TYPES >::type Transform
Applies a transformation to every type in a type list.
typename GetTypeImpl< TUPLE, D >::type GetType
Gives the specified type from a type list.