1 | /******************************************************************************* |
2 | Copyright (c) The Taichi Authors (2016- ). All Rights Reserved. |
3 | The use of this software is governed by the LICENSE file. |
4 | *******************************************************************************/ |
5 | |
6 | #pragma once |
7 | |
8 | #include <cstring> |
9 | #include <string> |
10 | #include <map> |
11 | #include <vector> |
12 | #include <functional> |
13 | #include <memory> |
14 | #include <iostream> |
15 | |
16 | namespace taichi { |
17 | |
18 | namespace meta { |
19 | template <template <int> class F, int bgn, int end, typename... Args> |
20 | struct RepeatFunctionHelper { |
21 | TI_FORCE_INLINE static void run(Args &&...args) { |
22 | F<bgn>::run(args...); |
23 | RepeatFunctionHelper<F, bgn + 1, end, Args...>::run( |
24 | std::forward<Args>(args)...); |
25 | } |
26 | }; |
27 | |
28 | template <template <int> class F, int bgn, typename... Args> |
29 | struct RepeatFunctionHelper<F, bgn, bgn, Args...> { |
30 | TI_FORCE_INLINE static void run(Args &&...args) { |
31 | return; |
32 | } |
33 | }; |
34 | |
35 | template <template <int> class F, int bgn, int end, typename... Args> |
36 | TI_FORCE_INLINE void repeat_function(Args &&...args) { |
37 | RepeatFunctionHelper<F, bgn, end, Args...>::run(std::forward<Args>(args)...); |
38 | } |
39 | } // namespace meta |
40 | |
41 | using meta::repeat_function; |
42 | |
43 | template <typename option, typename... Args> |
44 | struct type_switch { |
45 | using type = typename std::conditional< |
46 | std::is_same<typename option::first_type, std::true_type>::value, |
47 | typename option::second_type, |
48 | typename type_switch<Args...>::type>::type; |
49 | }; |
50 | |
51 | template <typename option> |
52 | struct type_switch<option> { |
53 | static_assert( |
54 | std::is_same<typename option::first_type, std::true_type>::value, |
55 | "None of the options in type_switch works." ); |
56 | using type = typename option::second_type; |
57 | }; |
58 | |
59 | template <typename... Args> |
60 | using type_switch_t = typename type_switch<Args...>::type; |
61 | |
62 | template <typename T, typename G> |
63 | struct copy_refcv { |
64 | TI_STATIC_ASSERT( |
65 | (std::is_same<G, std::remove_cv_t<std::remove_reference_t<G>>>::value)); |
66 | static constexpr bool has_lvalue_ref = std::is_lvalue_reference<T>::value; |
67 | static constexpr bool has_rvalue_ref = std::is_rvalue_reference<T>::value; |
68 | static constexpr bool has_const = |
69 | std::is_const<std::remove_reference_t<T>>::value; |
70 | static constexpr bool has_volatile = |
71 | std::is_volatile<std::remove_reference_t<T>>::value; |
72 | using G1 = std::conditional_t<has_const, const G, G>; |
73 | using G2 = std::conditional_t<has_volatile, volatile G1, G1>; |
74 | using G3 = std::conditional_t<has_lvalue_ref, G2 &, G2>; |
75 | using type = std::conditional_t<has_rvalue_ref, G3 &&, G3>; |
76 | }; |
77 | |
78 | template <typename T, typename G> |
79 | using copy_refcv_t = typename copy_refcv<T, G>::type; |
80 | |
81 | template <class T, template <class...> class Template> |
82 | struct is_specialization : std::false_type {}; |
83 | |
84 | template <template <class...> class Template, class... Args> |
85 | struct is_specialization<Template<Args...>, Template> : std::true_type {}; |
86 | |
87 | TI_STATIC_ASSERT((std::is_same<const volatile int, volatile const int>::value)); |
88 | TI_STATIC_ASSERT( |
89 | (std::is_same<int, |
90 | std::remove_volatile_t< |
91 | std::remove_const_t<const volatile int>>>::value)); |
92 | TI_STATIC_ASSERT( |
93 | (std::is_same<int, |
94 | std::remove_const_t< |
95 | std::remove_volatile_t<const volatile int>>>::value)); |
96 | TI_STATIC_ASSERT((std::is_same<int &, std::add_const_t<int &>>::value)); |
97 | TI_STATIC_ASSERT((std::is_same<copy_refcv_t<int, real>, real>::value)); |
98 | TI_STATIC_ASSERT((std::is_same<copy_refcv_t<int &, real>, real &>::value)); |
99 | TI_STATIC_ASSERT((copy_refcv<const int &, real>::has_lvalue_ref)); |
100 | TI_STATIC_ASSERT( |
101 | (std::is_same<copy_refcv<const int &, real>::G2, const real>::value)); |
102 | TI_STATIC_ASSERT( |
103 | (std::is_same<copy_refcv_t<const int &, real>, const real &>::value)); |
104 | TI_STATIC_ASSERT((std::is_same<copy_refcv_t<const volatile int &, real>, |
105 | const volatile real &>::value)); |
106 | TI_STATIC_ASSERT((is_specialization<std::vector<int>, std::vector>::value)); |
107 | |
108 | } // namespace taichi |
109 | |