SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
binary_operation.hpp
Go to the documentation of this file.
1 /*
2 Copyrightrandom_unique_numbers 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef SIG_UTIL_BINARY_OPERATION_HPP
9 #define SIG_UTIL_BINARY_OPERATION_HPP
10 
11 #include "../helper/helper_modules.hpp"
12 #include "../helper/container_helper.hpp"
13 
14 
16 
17 namespace sig
18 {
19 
21 
28 template <class OP, class T1, class T2,
29  typename std::enable_if<
30  (!impl::container_traits<typename impl::remove_const_reference<T1>::type>::exist) && (!impl::container_traits<typename impl::remove_const_reference<T2>::type>::exist)
31  >::type*& = enabler
32 >
33 auto binary_operation(OP&& func, T1&& v1, T2&& v2)
34  ->typename impl::remove_const_reference< decltype(impl::eval(std::forward<OP>(func), std::forward<T1>(v1), std::forward<T2>(v2)))>::type
35 {
36  return std::forward<OP>(func)(std::forward<T1>(v1), std::forward<T2>(v2));
37 }
38 
40 template <class OP, class C1, class C2,
41  class CR1 = typename impl::remove_const_reference<C1>::type,
42  class CR2 = typename impl::remove_const_reference<C2>::type,
43  class AT1 = typename impl::forward_element<C1>::type,
44  class AT2 = typename impl::forward_element<C2>::type,
45  typename std::enable_if<
46  impl::container_traits<CR1>::exist && impl::container_traits<CR2>::exist
47  >::type*& = enabler
48 >
49 auto binary_operation(OP&& func, C1&& c1, C2&& c2)
50  ->typename impl::container_traits<CR1>::template rebind<
51  typename impl::remove_const_reference<decltype(impl::eval(
52  std::forward<OP>(func),
53  std::declval<AT1>(),
54  std::declval<AT2>()
55  ))>::type
56  >
57 {
58  using RT = decltype(impl::eval(std::forward<OP>(func), std::declval<AT1>(), std::declval<AT2>()));
59  using R = typename impl::container_traits<CR1>::template rebind<RT>;
60 
61  const uint length = min(c1.size(), c2.size());
62  R result = impl::container_traits<R>::make(length);
63 
64  iterative_make(length, result, std::forward<OP>(func), impl::begin(std::forward<C1>(c1)), impl::begin(std::forward<C2>(c2)));
65  return result;
66 }
67 
69 template <class OP, class C, class T,
70  class CR = typename impl::remove_const_reference<C>::type,
71  class ET = typename impl::forward_element<C>::type,
72  typename std::enable_if<
73  impl::container_traits<CR>::exist && (!impl::container_traits<typename impl::remove_const_reference<T>::type>::exist)
74  >::type*& = enabler
75 >
76 auto binary_operation(OP&& func, C&& c, T&& v)
77  ->typename impl::container_traits<CR>::template rebind<
78  typename impl::remove_const_reference<decltype(impl::eval(
79  std::forward<OP>(func),
80  std::declval<ET>(),
81  v
82  ))>::type
83  >
84 {
85  using RT = decltype(impl::eval(std::forward<OP>(func), std::declval<ET>(), v));
86  using R = typename impl::container_traits<CR>::template rebind<RT>;
87 
88  R result = impl::container_traits<R>::make(c.size());
89 
90  for (auto&& e : std::forward<C>(c)){
91  impl::container_traits<R>::add_element(result, std::forward<OP>(func)(static_cast<ET>(e), v));
92  }
93  return result;
94 }
95 
97 template <class OP, class T, class C,
98  class ET = typename impl::forward_element<C>::type,
99  class CR = typename impl::remove_const_reference<C>::type,
100  typename std::enable_if<
101  (!impl::container_traits<typename impl::remove_const_reference<T>::type>::exist) && impl::container_traits<CR>::exist
102  >::type*& = enabler
103 >
104 auto binary_operation(OP&& func, T&& v, C&& c)
105  ->typename impl::container_traits<CR>::template rebind<
106  typename impl::remove_const_reference<decltype(impl::eval(
107  std::forward<OP>(func),
108  v,
109  std::declval<ET>()
110  ))>::type
111  >
112 {
113  using RT = decltype(impl::eval(std::forward<OP>(func), v, std::declval<ET>()));
114  using R = typename impl::container_traits<CR>::template rebind<RT>;
115 
116  R result = impl::container_traits<R>::make(c.size());
117 
118  for (auto&& e : std::forward<C>(c)){
119  impl::container_traits<R>::add_element(result, std::forward<OP>(func)(v, static_cast<ET>(e)));
120  }
121  return result;
122 }
123 
124 
125 
126 template <class T1, class T2>
127 auto plus(T1&& v1, T2&& v2)
128  ->decltype(binary_operation(plus_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
129 {
130  return binary_operation(plus_t(), std::forward<T1>(v1), std::forward<T2>(v2));
131 }
132 
133 
134 template <class T1, class T2>
135 auto minus(T1&& v1, T2&& v2)
136  ->decltype(binary_operation(minus_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
137 {
138  return binary_operation(minus_t(), std::forward<T1>(v1), std::forward<T2>(v2));
139 }
140 
141 
142 template <class T1, class T2>
143 auto mult(T1&& v1, T2&& v2)
144  ->decltype(binary_operation(mult_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
145 {
146  return binary_operation(mult_t(), std::forward<T1>(v1), std::forward<T2>(v2));
147 }
148 
149 
150 template <class T1, class T2>
151 auto div(T1&& v1, T2&& v2)
152  ->decltype(binary_operation(div_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
153 {
154  return binary_operation(div_t(), std::forward<T1>(v1), std::forward<T2>(v2));
155 }
156 
157 
158 template <class T1, class T2,
159  class TR1 = typename impl::remove_const_reference<T1>::type,
160  class TR2 = typename impl::remove_const_reference<T2>::type,
161  typename std::enable_if<
162  impl::container_traits<TR1>::exist || impl::container_traits<TR2>::exist
163  >::type*& = enabler
164 >
165 auto operator+(T1&& v1, T2&& v2)
166  ->decltype(binary_operation(plus_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
167 {
168  return binary_operation(plus_t(), std::forward<T1>(v1), std::forward<T2>(v2));
169 }
170 
171 
172 
173 template <class T1, class T2,
174  class TR1 = typename impl::remove_const_reference<T1>::type,
175  class TR2 = typename impl::remove_const_reference<T2>::type,
176  typename std::enable_if<
177  impl::container_traits<TR1>::exist || impl::container_traits<TR2>::exist
178  >::type*& = enabler
179 >
180 auto operator-(T1&& v1, T2&& v2)
181  ->decltype(binary_operation(minus_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
182 {
183  return binary_operation(minus_t(), std::forward<T1>(v1), std::forward<T2>(v2));
184 }
185 
186 
187 
188 template <class T1, class T2,
189  class TR1 = typename impl::remove_const_reference<T1>::type,
190  class TR2 = typename impl::remove_const_reference<T2>::type,
191  typename std::enable_if<
192  impl::container_traits<TR1>::exist || impl::container_traits<TR2>::exist
193  >::type*& = enabler
194 >
195 auto operator*(T1&& v1, T2&& v2)
196  ->decltype(binary_operation(mult_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
197 {
198  return binary_operation(mult_t(), std::forward<T1>(v1), std::forward<T2>(v2));
199 }
200 
201 
202 
203 template <class T1, class T2,
204  class TR1 = typename impl::remove_const_reference<T1>::type,
205  class TR2 = typename impl::remove_const_reference<T2>::type,
206  typename std::enable_if<
207  impl::container_traits<TR1>::exist || impl::container_traits<TR2>::exist
208  >::type*& = enabler
209 >
210 auto operator/(T1&& v1, T2&& v2)
211  ->decltype(binary_operation(div_t(), std::forward<T1>(v1), std::forward<T2>(v2)))
212 {
213  return binary_operation(div_t(), std::forward<T1>(v1), std::forward<T2>(v2));
214 }
215 
216 
217 
218 /*
220 #define SIG_MakeBinaryOperation(FunctionName, Operator)\
221  template <class T1, class T2,\
222  typename std::enable_if<\
223  (!impl::container_traits<typename impl::remove_const_reference<T1>::type>::exist) && (!impl::container_traits<typename impl::remove_const_reference<T2>::type>::exist)\
224  >::type*& = enabler\
225  >\
226  auto FunctionName(T1&& v1, T2&& v2) ->typename impl::remove_const_reference<decltype(std::forward<T1>(v1) Operator std::forward<T2>(v2))>::type\
227  {\
228  return std::forward<T1>(v1) Operator std::forward<T2>(v2); \
229  }\
230 \
231  template <class C1, class C2,\
232  class CR1 = typename impl::remove_const_reference<C1>::type, \
233  class CR2 = typename impl::remove_const_reference<C2>::type, \
234  class AT1 = typename impl::forward_element<C1>::type,\
235  class AT2 = typename impl::forward_element<C2>::type,\
236  typename std::enable_if<\
237  impl::container_traits<CR1>::exist && impl::container_traits<CR2>::exist\
238  >::type*& = enabler\
239  >\
240  auto FunctionName(C1&& c1, C2&& c2)\
241  ->typename impl::container_traits<CR1>::template rebind<\
242  typename impl::remove_const_reference<decltype(\
243  std::declval<AT1>() Operator std::declval<AT2>()\
244  )>::type\
245  >\
246  {\
247  return binary_operation([](AT1 v1, AT2 v2){ return static_cast<AT1>(v1) Operator static_cast<AT2>(v2); }, std::forward<C1>(c1), std::forward<C2>(c2)); \
248  }\
249 \
250  template <class C, class T,\
251  class CR = typename impl::remove_const_reference<C>::type,\
252  class ET = typename impl::forward_element<C>::type,\
253  typename std::enable_if<\
254  impl::container_traits<CR>::exist && (!impl::container_traits<typename impl::remove_const_reference<T>::type>::exist)\
255  >::type*& = enabler\
256  >\
257  auto FunctionName(C&& c, T&& v)\
258  ->typename impl::container_traits<CR>::template rebind<\
259  typename impl::remove_const_reference<decltype(\
260  std::declval<ET>() Operator v\
261  )>::type\
262  >\
263  {\
264  return binary_operation([](ET v1, T v2){ return static_cast<ET>(v1) Operator v2; }, std::forward<C>(c), std::forward<T>(v)); \
265  }\
266 \
267  template <class T, class C,\
268  class ET = typename impl::forward_element<C>::type, \
269  class CR = typename impl::remove_const_reference<C>::type,\
270  typename std::enable_if<\
271  (!impl::container_traits<typename impl::remove_const_reference<T>::type>::exist) && impl::container_traits<CR>::exist\
272  >::type*& = enabler\
273  >\
274  auto FunctionName(T&& v, C&& c)\
275  ->typename impl::container_traits<CR>::template rebind<\
276  typename impl::remove_const_reference<decltype(\
277  v Operator std::declval<ET>()\
278  )>::type\
279  >\
280  {\
281  return binary_operation([](T v1, ET v2){ return v1 Operator static_cast<ET>(v2); }, std::forward<T>(v), std::forward<C>(c)); \
282  }\
283 */
284 
286 
297 //SIG_MakeBinaryOperation(plus, +);
298 
300 
303 //SIG_MakeBinaryOperation(minus, -);
304 
306 
309 //SIG_MakeBinaryOperation(mult, *);
310 //SIG_MakeBinaryOperation(multiplies, *);
311 
313 
316 //SIG_MakeBinaryOperation(div, / );
317 //SIG_MakeBinaryOperation(divides, / );
318 
319 
320 }
321 #endif
auto operator*(T1 &&v1, T2 &&v2) -> decltype(binary_operation(mult_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto operator+(T1 &&v1, T2 &&v2) -> decltype(binary_operation(plus_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto binary_operation(OP &&func, T1 &&v1, T2 &&v2) -> typename impl::remove_const_reference< decltype(impl::eval(std::forward< OP >(func), std::forward< T1 >(v1), std::forward< T2 >(v2)))>::type
二項演算 (scalar and scalar)
auto plus(T1 &&v1, T2 &&v2) -> decltype(binary_operation(plus_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
加法を行う関数オブジェクト
void * enabler
auto div(T1 &&v1, T2 &&v2) -> decltype(binary_operation(div_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto operator/(T1 &&v1, T2 &&v2) -> decltype(binary_operation(div_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto mult(T1 &&v1, T2 &&v2) -> decltype(binary_operation(mult_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto minus(T1 &&v1, T2 &&v2) -> decltype(binary_operation(minus_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto min(T v) -> T
減法を行う関数オブジェクト
auto operator-(T1 &&v1, T2 &&v2) -> decltype(binary_operation(minus_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto eval(F &&f, Args &&...args) -> decltype(f(std::forward< Args >(args)...))
Definition: eval.hpp:37
除法を行う関数オブジェクト
Definition: array.hpp:15
乗法を行う関数オブジェクト
auto begin(C &&c) -> std::move_iterator< typename RC::iterator >
void iterative_make(uint loop, C &dest, F &&func, Its...iterators)