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
16namespace taichi {
17
18namespace meta {
19template <template <int> class F, int bgn, int end, typename... Args>
20struct 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
28template <template <int> class F, int bgn, typename... Args>
29struct RepeatFunctionHelper<F, bgn, bgn, Args...> {
30 TI_FORCE_INLINE static void run(Args &&...args) {
31 return;
32 }
33};
34
35template <template <int> class F, int bgn, int end, typename... Args>
36TI_FORCE_INLINE void repeat_function(Args &&...args) {
37 RepeatFunctionHelper<F, bgn, end, Args...>::run(std::forward<Args>(args)...);
38}
39} // namespace meta
40
41using meta::repeat_function;
42
43template <typename option, typename... Args>
44struct 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
51template <typename option>
52struct 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
59template <typename... Args>
60using type_switch_t = typename type_switch<Args...>::type;
61
62template <typename T, typename G>
63struct 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
78template <typename T, typename G>
79using copy_refcv_t = typename copy_refcv<T, G>::type;
80
81template <class T, template <class...> class Template>
82struct is_specialization : std::false_type {};
83
84template <template <class...> class Template, class... Args>
85struct is_specialization<Template<Args...>, Template> : std::true_type {};
86
87TI_STATIC_ASSERT((std::is_same<const volatile int, volatile const int>::value));
88TI_STATIC_ASSERT(
89 (std::is_same<int,
90 std::remove_volatile_t<
91 std::remove_const_t<const volatile int>>>::value));
92TI_STATIC_ASSERT(
93 (std::is_same<int,
94 std::remove_const_t<
95 std::remove_volatile_t<const volatile int>>>::value));
96TI_STATIC_ASSERT((std::is_same<int &, std::add_const_t<int &>>::value));
97TI_STATIC_ASSERT((std::is_same<copy_refcv_t<int, real>, real>::value));
98TI_STATIC_ASSERT((std::is_same<copy_refcv_t<int &, real>, real &>::value));
99TI_STATIC_ASSERT((copy_refcv<const int &, real>::has_lvalue_ref));
100TI_STATIC_ASSERT(
101 (std::is_same<copy_refcv<const int &, real>::G2, const real>::value));
102TI_STATIC_ASSERT(
103 (std::is_same<copy_refcv_t<const int &, real>, const real &>::value));
104TI_STATIC_ASSERT((std::is_same<copy_refcv_t<const volatile int &, real>,
105 const volatile real &>::value));
106TI_STATIC_ASSERT((is_specialization<std::vector<int>, std::vector>::value));
107
108} // namespace taichi
109