NiHu  2.0
lambda.hpp
Go to the documentation of this file.
1 // This file is a part of NiHu, a C++ BEM template library.
2 //
3 // Copyright (C) 2012-2014 Peter Fiala <fiala@hit.bme.hu>
4 // Copyright (C) 2012-2014 Peter Rucz <rucz@hit.bme.hu>
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
25 #ifndef LAMBDA_HPP_INCLUDED
26 #define LAMBDA_HPP_INCLUDED
27 
28 #include <type_traits>
29 
30 namespace tmp
31 {
33  template <unsigned N, class T, class ...Args>
34  struct select_argument : select_argument<N-1, Args...> {};
35 
37  template <class T, class ...Args>
38  struct select_argument<1U, T, Args...>
39  {
40  typedef T type;
41  };
42 
47  template <unsigned N>
48  struct arg
49  {
50  template <class...Args>
51  struct apply : select_argument<N, Args...> {};
52  };
53 
55  typedef arg<1> _1;
57  typedef arg<2> _2;
59  typedef arg<3> _3;
60 
61 
63  struct void_;
64 
68  template <class C>
69  struct isPlaceholder : std::false_type {};
70 
71  template <unsigned N>
72  struct isPlaceholder<arg<N> > : std::true_type {};
73 
74 
78  template <class C>
79  struct isPlaceholderExpression : std::false_type {};
80 
81  template <unsigned N>
82  struct isPlaceholderExpression<arg<N> > : std::true_type {};
83 
84  // Forward declaration of the general case
85  template <class T, class...Args>
87 
88  // General declaration of the inner impl class
89  // Decision is made based on the first argument
90  // (See specialisation below)
91  template <class First, class...Args>
93 
94  // True branch
95  // First parameter is a placeholder expression
96  // Recursion tail for true_type
97  template <class...Args>
98  struct containsPlaceholderExpressionImpl<std::true_type, Args...> :
99  std::true_type {};
100 
101  // Recursion tail for false_type
102  template <>
103  struct containsPlaceholderExpressionImpl<std::false_type> :
104  std::false_type {};
105 
106  // General case, further recursion
107  template <class...Args>
108  struct containsPlaceholderExpressionImpl<std::false_type, Args...> :
109  containsPlaceholderExpression<Args...> {};
110 
111  // General case
112  template <class T, class...Args>
114  typename isPlaceholderExpression<T>::type,
115  Args...
116  > {};
117 
118  // Specialisation for metafunction
119  template <template <class...Args> class MF, class...Args>
120  struct isPlaceholderExpression<MF<Args...> > :
121  containsPlaceholderExpression<Args...> {};
122 
123 
124  namespace internal
125  {
126  // The general case
127  template <class Fun>
128  struct lambda_plExp; // dummy case
129 
130  // Specialisation for placeholder
131  template <unsigned N>
132  struct lambda_plExp<arg<N> >
133  {
134  struct type
135  {
136  template <class...Args>
137  struct apply : arg<N>::template apply<Args...> {};
138  };
139  };
140 
141  // Specialisation for metafunction for 1 parameter
143  template <template <class a> class MetaFun, class a1>
144  struct lambda_plExp<MetaFun<a1> >
145  {
146  struct type
147  {
148  template <class...Args>
149  struct apply
150  : MetaFun<
151  typename lambda_plExp<a1>::type::template apply<Args...>::type
152  >
153  {};
154  };
155  };
156 
157  // Conditional eveluation of arguments
158  // First argument tells if a is a placeholder expression
159  // General case
160  template <class BOOL, class a, class...Args>
161  struct cond_eval_arg;
162 
163  // Specialisation for true case (a is a plhexp)
164  template <class a, class...Args>
165  struct cond_eval_arg<std::true_type, a, Args...> :
166  lambda_plExp<a>::type::template apply<Args...> {};
167 
168  // Specialisation for false case (a is not a plhexp)
169  template <class a, class...Args>
170  struct cond_eval_arg<std::false_type, a, Args...>
171  {
172  typedef a type;
173  };
174 
175  // Two parameter metafun
176  template <template <class a, class b> class MetaFun, class a1, class a2>
177  struct lambda_plExp<MetaFun<a1, a2> >
178  {
179  struct type
180  {
181  template <class A1 = void_, class A2 = void_>
182  struct apply : MetaFun<
183  typename cond_eval_arg<
184  typename isPlaceholderExpression<a1>::type,
185  a1, A1, A2
186  >::type,
187  typename cond_eval_arg<
188  typename isPlaceholderExpression<a2>::type,
189  a2, A1, A2
190  >::type
191  > {};
192  };
193  };
194 
195  // Three parameter metafun (not used yet)
196  template <template <class a1, class a2, class a3> class MetaFun, class a1, class a2, class a3>
197  struct lambda_plExp<MetaFun<a1, a2, a3> >
198  {
199  typedef struct _tmp
200  {
201  template <class A1 = void_, class A2 = void_>
202  struct apply : MetaFun<
203  typename cond_eval_arg<
204  typename isPlaceholderExpression<a1>::type,
205  a1, A1, A2
206  >::type,
207  typename cond_eval_arg<
208  typename isPlaceholderExpression<a2>::type,
209  a2, A1, A2
210  >::type,
211  typename cond_eval_arg<
212  typename isPlaceholderExpression<a3>::type,
213  a3, A1, A2
214  >::type
215  > {};
216  } type;
217  };
218  }
219 
220 
226  template <class Exp>
227  struct lambda : std::conditional<
228  isPlaceholderExpression<Exp>::type::value,
229  typename internal::lambda_plExp<Exp>::type,
230  Exp
231  > {};
232 
238  template <class Fun, class...Args>
239  struct apply : lambda<Fun>::type::template apply<Args...> {};
240 }
241 
242 #endif
243 
tmp
template metaprogramming functions
Definition: asymptotic_types.hpp:101
tmp::containsPlaceholderExpressionImpl
Definition: lambda.hpp:92
tmp::_2
arg< 2 > _2
shorthand for selecting the 2nd argument
Definition: lambda.hpp:57
tmp::arg
placeholder that selects N-th argument
Definition: lambda.hpp:48
tmp::containsPlaceholderExpression
Definition: lambda.hpp:86
tmp::apply
The apply metafunction shortcut for lambda evaluation.
Definition: lambda.hpp:239
tmp::isPlaceholderExpression
metafunction returning std::true_type if its argument is a placeholder expression
Definition: lambda.hpp:79
tmp::_1
arg< 1 > _1
shorthand for selecting the 1st argument
Definition: lambda.hpp:55
tmp::isPlaceholder
metafunction returning std::true_type if its argument is a placeholder
Definition: lambda.hpp:69
tmp::lambda
generate metafunction class from placeholder expression
Definition: lambda.hpp:227
tmp::arg::apply
Definition: lambda.hpp:51
tmp::select_argument
select N-th argument of a variadic template
Definition: lambda.hpp:34
tmp::_3
arg< 3 > _3
shorthand for selecting the 3rd argument
Definition: lambda.hpp:59