1 /*-----------------------------------------------------------------------------+
2 Copyright (c) 2007-2009: Joachim Faulhaber
3 +------------------------------------------------------------------------------+
4 Distributed under the Boost Software License, Version 1.0.
5 (See accompanying file LICENCE.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt)
7 +-----------------------------------------------------------------------------*/
8 #ifndef BOOST_ICL_FUNCTORS_HPP_JOFA_080315
9 #define BOOST_ICL_FUNCTORS_HPP_JOFA_080315
12 #include <boost/type_traits.hpp>
13 #include <boost/mpl/if.hpp>
14 #include <boost/icl/type_traits/identity_element.hpp>
15 #include <boost/icl/type_traits/unit_element.hpp>
16 #include <boost/icl/type_traits/is_set.hpp>
17 #include <boost/icl/type_traits/has_set_semantics.hpp>
19 namespace boost{namespace icl
21 // ------------------------------------------------------------------------
22 template <typename Type> struct identity_based_inplace_combine
23 : public std::binary_function<Type&, const Type&, void>
25 inline static Type identity_element() { return boost::icl::identity_element<Type>::value(); }
28 // ------------------------------------------------------------------------
29 template <typename Type> struct unit_element_based_inplace_combine
30 : public std::binary_function<Type&, const Type&, void>
32 inline static Type identity_element() { return boost::icl::unit_element<Type>::value(); }
35 // ------------------------------------------------------------------------
36 template <typename Type> struct inplace_identity
37 : public identity_based_inplace_combine<Type>
39 typedef inplace_identity<Type> type;
40 void operator()(Type&, const Type&)const{}
44 inline std::string unary_template_to_string<inplace_identity>::apply()
47 // ------------------------------------------------------------------------
48 template <typename Type> struct inplace_erasure
49 : public identity_based_inplace_combine<Type>
51 typedef inplace_erasure<Type> type;
52 typedef identity_based_inplace_combine<Type> base_type;
54 void operator()(Type& object, const Type& operand)const
57 //identity_element(); //JODO Old gcc-3.4.4 does not compile this
58 object = base_type::identity_element(); //<-- but this.
63 inline std::string unary_template_to_string<inplace_erasure>::apply()
66 // ------------------------------------------------------------------------
67 template <typename Type> struct inplace_plus
68 : public identity_based_inplace_combine<Type>
70 typedef inplace_plus<Type> type;
72 void operator()(Type& object, const Type& operand)const
73 { object += operand; }
75 static void version(Type&){}
79 inline std::string unary_template_to_string<inplace_plus>::apply() { return "+="; }
81 // ------------------------------------------------------------------------
82 template <typename Type> struct inplace_minus
83 : public identity_based_inplace_combine<Type>
85 typedef inplace_minus<Type> type;
87 void operator()(Type& object, const Type& operand)const
88 { object -= operand; }
92 inline std::string unary_template_to_string<inplace_minus>::apply() { return "-="; }
94 // ------------------------------------------------------------------------
95 template <typename Type> struct inplace_bit_add
96 : public identity_based_inplace_combine<Type>
98 typedef inplace_bit_add<Type> type;
100 void operator()(Type& object, const Type& operand)const
101 { object |= operand; }
103 static void version(Type&){}
107 inline std::string unary_template_to_string<inplace_bit_add>::apply() { return "b|="; }
109 // ------------------------------------------------------------------------
110 template <typename Type> struct inplace_bit_subtract
111 : public identity_based_inplace_combine<Type>
113 typedef inplace_bit_subtract<Type> type;
115 void operator()(Type& object, const Type& operand)const
116 { object &= ~operand; }
120 inline std::string unary_template_to_string<inplace_bit_subtract>::apply() { return "b-="; }
122 // ------------------------------------------------------------------------
123 template <typename Type> struct inplace_bit_and
124 : public identity_based_inplace_combine<Type>
126 typedef inplace_bit_and<Type> type;
128 void operator()(Type& object, const Type& operand)const
129 { object &= operand; }
133 inline std::string unary_template_to_string<inplace_bit_and>::apply() { return "b&="; }
135 // ------------------------------------------------------------------------
136 template <typename Type> struct inplace_bit_xor
137 : public identity_based_inplace_combine<Type>
139 typedef inplace_bit_xor<Type> type;
141 void operator()(Type& object, const Type& operand)const
142 { object ^= operand; }
145 // ------------------------------------------------------------------------
146 template <typename Type> struct inplace_et
147 : public identity_based_inplace_combine<Type>
149 typedef inplace_et<Type> type;
151 void operator()(Type& object, const Type& operand)const
152 { object &= operand; }
156 inline std::string unary_template_to_string<inplace_et>::apply() { return "&="; }
158 // ------------------------------------------------------------------------
159 template <typename Type> struct inplace_caret
160 : public identity_based_inplace_combine<Type>
162 typedef inplace_caret<Type> type;
164 void operator()(Type& object, const Type& operand)const
165 { object ^= operand; }
169 inline std::string unary_template_to_string<inplace_caret>::apply() { return "^="; }
171 // ------------------------------------------------------------------------
172 template <typename Type> struct inplace_insert
173 : public identity_based_inplace_combine<Type>
175 typedef inplace_insert<Type> type;
177 void operator()(Type& object, const Type& operand)const
178 { insert(object,operand); }
182 inline std::string unary_template_to_string<inplace_insert>::apply() { return "ins="; }
184 // ------------------------------------------------------------------------
185 template <typename Type> struct inplace_erase
186 : public identity_based_inplace_combine<Type>
188 typedef inplace_erase<Type> type;
190 void operator()(Type& object, const Type& operand)const
191 { erase(object,operand); }
195 inline std::string unary_template_to_string<inplace_erase>::apply() { return "ers="; }
197 // ------------------------------------------------------------------------
198 template <typename Type> struct inplace_star
199 : public identity_based_inplace_combine<Type> //JODO unit_element_
201 typedef inplace_star<Type> type;
203 void operator()(Type& object, const Type& operand)const
204 { object *= operand; }
208 inline std::string unary_template_to_string<inplace_star>::apply() { return "*="; }
210 // ------------------------------------------------------------------------
211 template <typename Type> struct inplace_slash
212 : public identity_based_inplace_combine<Type> //JODO unit_element_
214 typedef inplace_slash<Type> type;
216 void operator()(Type& object, const Type& operand)const
217 { object /= operand; }
221 inline std::string unary_template_to_string<inplace_slash>::apply() { return "/="; }
223 // ------------------------------------------------------------------------
224 template <typename Type> struct inplace_max
225 : public identity_based_inplace_combine<Type>
227 typedef inplace_max<Type> type;
229 void operator()(Type& object, const Type& operand)const
237 inline std::string unary_template_to_string<inplace_max>::apply() { return "max="; }
239 // ------------------------------------------------------------------------
240 template <typename Type> struct inplace_min
241 : public identity_based_inplace_combine<Type>
243 typedef inplace_min<Type> type;
245 void operator()(Type& object, const Type& operand)const
253 inline std::string unary_template_to_string<inplace_min>::apply() { return "min="; }
255 //--------------------------------------------------------------------------
256 // Inter_section functor
257 //--------------------------------------------------------------------------
258 template<class Type> struct inter_section
259 : public identity_based_inplace_combine<Type>
261 typedef typename boost::mpl::
262 if_<has_set_semantics<Type>,
263 icl::inplace_et<Type>,
264 icl::inplace_plus<Type>
268 void operator()(Type& object, const Type& operand)const
270 type()(object, operand);
274 //--------------------------------------------------------------------------
276 //--------------------------------------------------------------------------
277 template<class Functor> struct inverse;
280 struct inverse<icl::inplace_plus<Type> >
281 { typedef icl::inplace_minus<Type> type; };
284 struct inverse<icl::inplace_minus<Type> >
285 { typedef icl::inplace_plus<Type> type; };
288 struct inverse<icl::inplace_bit_add<Type> >
289 { typedef icl::inplace_bit_subtract<Type> type; };
292 struct inverse<icl::inplace_bit_subtract<Type> >
293 { typedef icl::inplace_bit_add<Type> type; };
296 struct inverse<icl::inplace_et<Type> >
297 { typedef icl::inplace_caret<Type> type; };
300 struct inverse<icl::inplace_caret<Type> >
301 { typedef icl::inplace_et<Type> type; };
304 struct inverse<icl::inplace_bit_and<Type> >
305 { typedef icl::inplace_bit_xor<Type> type; };
308 struct inverse<icl::inplace_bit_xor<Type> >
309 { typedef icl::inplace_bit_and<Type> type; };
312 struct inverse<icl::inplace_star<Type> >
313 { typedef icl::inplace_slash<Type> type; };
316 struct inverse<icl::inplace_slash<Type> >
317 { typedef icl::inplace_star<Type> type; };
320 struct inverse<icl::inplace_max<Type> >
321 { typedef icl::inplace_min<Type> type; };
324 struct inverse<icl::inplace_min<Type> >
325 { typedef icl::inplace_max<Type> type; };
328 struct inverse<icl::inplace_identity<Type> >
329 { typedef icl::inplace_erasure<Type> type; };
332 template<class Functor>
336 remove_reference<typename Functor::first_argument_type>::type argument_type;
337 typedef icl::inplace_erasure<argument_type> type;
341 //--------------------------------------------------------------------------
342 // Inverse inter_section functor
343 //--------------------------------------------------------------------------
345 struct inverse<icl::inter_section<Type> >
346 : public identity_based_inplace_combine<Type>
348 typedef typename boost::mpl::
349 if_<has_set_semantics<Type>,
350 icl::inplace_caret<Type>,
351 icl::inplace_minus<Type>
355 void operator()(Type& object, const Type& operand)const
357 type()(object, operand);
362 //--------------------------------------------------------------------------
363 // Positive or negative functor trait
364 //--------------------------------------------------------------------------
366 // A binary operation - is negative (or inverting) with respect to the
367 // neutral element iff it yields the inverse element if it is applied to the
370 // For a functor that wraps the inplace of op-assign version this is
374 // y = Functor::identity_element();
375 // Functor()(y, x); // y == inverse_of(x)
377 template<class Functor> struct is_negative;
379 template<class Functor>
382 typedef is_negative<Functor> type;
383 BOOST_STATIC_CONSTANT(bool, value = false);
387 struct is_negative<icl::inplace_minus<Type> >
389 typedef is_negative type;
390 BOOST_STATIC_CONSTANT(bool, value = true);
394 struct is_negative<icl::inplace_bit_subtract<Type> >
396 typedef is_negative type;
397 BOOST_STATIC_CONSTANT(bool, value = true);
400 //--------------------------------------------------------------------------
401 // Pro- or in-version functor
402 //--------------------------------------------------------------------------
403 template<class Combiner> struct conversion;
405 template<class Combiner>
408 typedef conversion<Combiner> type;
411 typename remove_reference<typename Combiner::first_argument_type
415 // The proversion of an op-assign functor o= lets the value unchanged
417 // Example += : (0 += x) == x
418 static argument_type proversion(const argument_type& value)
423 // The inversion of an op-assign functor o= inverts the value x
424 // to it's inverse element -x
426 // Example -= : (0 -= x) == -x
427 static argument_type inversion(const argument_type& value)
429 argument_type inverse = Combiner::identity_element();
430 Combiner()(inverse, value);
435 template<class Combiner> struct version : public conversion<Combiner>
437 typedef version<Combiner> type;
438 typedef conversion<Combiner> base_type;
439 typedef typename base_type::argument_type argument_type;
441 argument_type operator()(const argument_type& value)
442 { return base_type::proversion(value); }
445 template<>struct version<icl::inplace_minus<short > >{short operator()(short val){return -val;}};
446 template<>struct version<icl::inplace_minus<int > >{int operator()(int val){return -val;}};
447 template<>struct version<icl::inplace_minus<long > >{long operator()(long val){return -val;}};
448 template<>struct version<icl::inplace_minus<long long > >{long long operator()(long long val){return -val;}};
449 template<>struct version<icl::inplace_minus<float > >{float operator()(float val){return -val;}};
450 template<>struct version<icl::inplace_minus<double > >{double operator()(double val){return -val;}};
451 template<>struct version<icl::inplace_minus<long double> >{long double operator()(long double val){return -val;}};
454 struct version<icl::inplace_minus<Type> > : public conversion<icl::inplace_minus<Type> >
456 typedef version<icl::inplace_minus<Type> > type;
457 typedef conversion<icl::inplace_minus<Type> > base_type;
458 typedef typename base_type::argument_type argument_type;
460 Type operator()(const Type& value)
462 return base_type::inversion(value);
466 }} // namespace icl boost