• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
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 
17 #ifndef FRUIT_META_METAPROGRAMMING_H
18 #define FRUIT_META_METAPROGRAMMING_H
19 
20 #include <fruit/impl/meta/basics.h>
21 #include <fruit/impl/meta/vector.h>
22 
23 #include <fruit/impl/fruit_assert.h>
24 #include <fruit/impl/fruit_internal_forward_decls.h>
25 #include <fruit/impl/injection_errors.h>
26 #include <fruit/impl/meta/errors.h>
27 
28 #include <memory>
29 
30 namespace fruit {
31 namespace impl {
32 namespace meta {
33 
34 struct IsConstructible {
35   template <typename C, typename... Args>
36   struct apply;
37 
38   template <typename C, typename... Args>
39   struct apply<Type<C>, Type<Args>...> {
40     using type = Bool<std::is_constructible<C, Args...>::value>;
41   };
42 };
43 
44 struct IsConstructibleWithVector {
45   template <typename C, typename V>
46   struct apply;
47 
48   template <typename C, typename... Types>
49   struct apply<Type<C>, Vector<Type<Types>...>> {
50     using type = Bool<std::is_constructible<C, Types...>::value>;
51   };
52 };
53 
54 struct AddPointer {
55   template <typename T>
56   struct apply;
57 
58   template <typename T>
59   struct apply<Type<T>> {
60     using type = Type<T*>;
61   };
62 };
63 
64 struct IsCallable {
65   template <typename T>
66   struct apply;
67 
68   template <typename C>
69   struct apply<Type<C>> {
70     template <typename C1>
71     static Bool<true> test(decltype(&C1::operator()));
72 
73     template <typename>
74     static Bool<false> test(...);
75 
76     using type = decltype(test<C>(nullptr));
77   };
78 };
79 
80 struct GetCallOperatorSignature {
81   template <typename T>
82   struct apply;
83 
84   template <typename C>
85   struct apply<Type<C>> {
86     using type = Type<decltype(&C::operator())>;
87   };
88 };
89 
90 struct AddPointerToVector {
91   template <typename V>
92   struct apply;
93 
94   template <typename... Ts>
95   struct apply<Vector<Type<Ts>...>> {
96     using type = Vector<Type<Ts*>...>;
97   };
98 };
99 
100 struct GetNthTypeHelper {
101   template <typename N, typename... Ts>
102   struct apply;
103 
104   template <typename T, typename... Ts>
105   struct apply<Int<0>, T, Ts...> {
106     using type = T;
107   };
108 
109   template <int n, typename T, typename... Ts>
110   struct apply<Int<n>, T, Ts...> {
111     using type = GetNthTypeHelper(Int<n - 1>, Ts...);
112   };
113 };
114 
115 struct GetNthType {
116   template <typename N, typename V>
117   struct apply;
118 
119   template <typename N, typename... Ts>
120   struct apply<N, Vector<Ts...>> {
121     using type = GetNthTypeHelper(N, Ts...);
122   };
123 };
124 
125 struct FunctorResultHelper {
126   template <typename MethodSignature>
127   struct apply;
128 
129   template <typename Result, typename Functor, typename... Args>
130   struct apply<Type<Result (Functor::*)(Args...)>> {
131     using type = Type<Result>;
132   };
133 };
134 
135 struct FunctorResult {
136   template <typename F>
137   struct apply;
138 
139   template <typename F>
140   struct apply<Type<F>> {
141     using type = FunctorResultHelper(Type<decltype(&F::operator())>);
142   };
143 };
144 
145 struct FunctionSignatureHelper {
146   template <typename LambdaMethod>
147   struct apply;
148 
149   template <typename Result, typename LambdaObject, typename... Args>
150   struct apply<Type<Result (LambdaObject::*)(Args...) const>> {
151     using type = Type<Result(Args...)>;
152   };
153 };
154 
155 // Function is either a plain function type of the form T(*)(Args...) or a lambda.
156 struct FunctionSignature {
157   template <typename Function>
158   struct apply;
159 
160   template <typename Function>
161   struct apply<Type<Function>> {
162     using CandidateSignature = FunctionSignatureHelper(GetCallOperatorSignature(Type<Function>));
163     using type = If(Not(IsCallable(Type<Function>)), ConstructError(NotALambdaErrorTag, Type<Function>),
164                     If(Not(IsConstructible(AddPointer(CandidateSignature), Type<Function>)),
165                        ConstructError(FunctorUsedAsProviderErrorTag, Type<Function>), CandidateSignature));
166   };
167 
168   template <typename Result, typename... Args>
169   struct apply<Type<Result(Args...)>> {
170     using type = Type<Result(Args...)>;
171   };
172 
173   template <typename Result, typename... Args>
174   struct apply<Type<Result (*)(Args...)>> {
175     using type = Type<Result(Args...)>;
176   };
177 };
178 
179 } // namespace meta
180 } // namespace impl
181 } // namespace fruit
182 
183 #endif // FRUIT_META_METAPROGRAMMING_H
184