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
11 #include <boost/type_traits.hpp>
12 #include <boost/mpl/if.hpp>
13 #include <boost/icl/type_traits/identity_element.hpp>
14 #include <boost/icl/type_traits/unit_element.hpp>
15 #include <boost/icl/type_traits/is_set.hpp>
16 #include <boost/icl/type_traits/has_set_semantics.hpp>
18 namespace boost{namespace icl
20 // ------------------------------------------------------------------------
21 template <typename Type> struct identity_based_inplace_combine
23 typedef Type& first_argument_type;
24 typedef const Type& second_argument_type;
25 typedef void result_type;
26 inline static Type identity_element() { return boost::icl::identity_element<Type>::value(); }
29 // ------------------------------------------------------------------------
30 template <typename Type> struct unit_element_based_inplace_combine
32 typedef Type& first_argument_type;
33 typedef const Type& second_argument_type;
34 typedef void result_type;
35 inline static Type identity_element() { return boost::icl::unit_element<Type>::value(); }
38 // ------------------------------------------------------------------------
39 template <typename Type> struct inplace_identity
40 : public identity_based_inplace_combine<Type>
42 typedef inplace_identity<Type> type;
43 void operator()(Type&, const Type&)const{}
47 inline std::string unary_template_to_string<inplace_identity>::apply()
50 // ------------------------------------------------------------------------
51 template <typename Type> struct inplace_erasure
52 : public identity_based_inplace_combine<Type>
54 typedef inplace_erasure<Type> type;
55 typedef identity_based_inplace_combine<Type> base_type;
57 void operator()(Type& object, const Type& operand)const
60 //identity_element(); //JODO Old gcc-3.4.4 does not compile this
61 object = base_type::identity_element(); //<-- but this.
66 inline std::string unary_template_to_string<inplace_erasure>::apply()
69 // ------------------------------------------------------------------------
70 template <typename Type> struct inplace_plus
71 : public identity_based_inplace_combine<Type>
73 typedef inplace_plus<Type> type;
75 void operator()(Type& object, const Type& operand)const
76 { object += operand; }
78 static void version(Type&){}
82 inline std::string unary_template_to_string<inplace_plus>::apply() { return "+="; }
84 // ------------------------------------------------------------------------
85 template <typename Type> struct inplace_minus
86 : public identity_based_inplace_combine<Type>
88 typedef inplace_minus<Type> type;
90 void operator()(Type& object, const Type& operand)const
91 { object -= operand; }
95 inline std::string unary_template_to_string<inplace_minus>::apply() { return "-="; }
97 // ------------------------------------------------------------------------
98 template <typename Type> struct inplace_bit_add
99 : public identity_based_inplace_combine<Type>
101 typedef inplace_bit_add<Type> type;
103 void operator()(Type& object, const Type& operand)const
104 { object |= operand; }
106 static void version(Type&){}
110 inline std::string unary_template_to_string<inplace_bit_add>::apply() { return "b|="; }
112 // ------------------------------------------------------------------------
113 template <typename Type> struct inplace_bit_subtract
114 : public identity_based_inplace_combine<Type>
116 typedef inplace_bit_subtract<Type> type;
118 void operator()(Type& object, const Type& operand)const
119 { object &= ~operand; }
123 inline std::string unary_template_to_string<inplace_bit_subtract>::apply() { return "b-="; }
125 // ------------------------------------------------------------------------
126 template <typename Type> struct inplace_bit_and
127 : public identity_based_inplace_combine<Type>
129 typedef inplace_bit_and<Type> type;
131 void operator()(Type& object, const Type& operand)const
132 { object &= operand; }
136 inline std::string unary_template_to_string<inplace_bit_and>::apply() { return "b&="; }
138 // ------------------------------------------------------------------------
139 template <typename Type> struct inplace_bit_xor
140 : public identity_based_inplace_combine<Type>
142 typedef inplace_bit_xor<Type> type;
144 void operator()(Type& object, const Type& operand)const
145 { object ^= operand; }
148 // ------------------------------------------------------------------------
149 template <typename Type> struct inplace_et
150 : public identity_based_inplace_combine<Type>
152 typedef inplace_et<Type> type;
154 void operator()(Type& object, const Type& operand)const
155 { object &= operand; }
159 inline std::string unary_template_to_string<inplace_et>::apply() { return "&="; }
161 // ------------------------------------------------------------------------
162 template <typename Type> struct inplace_caret
163 : public identity_based_inplace_combine<Type>
165 typedef inplace_caret<Type> type;
167 void operator()(Type& object, const Type& operand)const
168 { object ^= operand; }
172 inline std::string unary_template_to_string<inplace_caret>::apply() { return "^="; }
174 // ------------------------------------------------------------------------
175 template <typename Type> struct inplace_insert
176 : public identity_based_inplace_combine<Type>
178 typedef inplace_insert<Type> type;
180 void operator()(Type& object, const Type& operand)const
181 { insert(object,operand); }
185 inline std::string unary_template_to_string<inplace_insert>::apply() { return "ins="; }
187 // ------------------------------------------------------------------------
188 template <typename Type> struct inplace_erase
189 : public identity_based_inplace_combine<Type>
191 typedef inplace_erase<Type> type;
193 void operator()(Type& object, const Type& operand)const
194 { erase(object,operand); }
198 inline std::string unary_template_to_string<inplace_erase>::apply() { return "ers="; }
200 // ------------------------------------------------------------------------
201 template <typename Type> struct inplace_star
202 : public identity_based_inplace_combine<Type> //JODO unit_element_
204 typedef inplace_star<Type> type;
206 void operator()(Type& object, const Type& operand)const
207 { object *= operand; }
211 inline std::string unary_template_to_string<inplace_star>::apply() { return "*="; }
213 // ------------------------------------------------------------------------
214 template <typename Type> struct inplace_slash
215 : public identity_based_inplace_combine<Type> //JODO unit_element_
217 typedef inplace_slash<Type> type;
219 void operator()(Type& object, const Type& operand)const
220 { object /= operand; }
224 inline std::string unary_template_to_string<inplace_slash>::apply() { return "/="; }
226 // ------------------------------------------------------------------------
227 template <typename Type> struct inplace_max
228 : public identity_based_inplace_combine<Type>
230 typedef inplace_max<Type> type;
232 void operator()(Type& object, const Type& operand)const
240 inline std::string unary_template_to_string<inplace_max>::apply() { return "max="; }
242 // ------------------------------------------------------------------------
243 template <typename Type> struct inplace_min
244 : public identity_based_inplace_combine<Type>
246 typedef inplace_min<Type> type;
248 void operator()(Type& object, const Type& operand)const
256 inline std::string unary_template_to_string<inplace_min>::apply() { return "min="; }
258 //--------------------------------------------------------------------------
259 // Inter_section functor
260 //--------------------------------------------------------------------------
261 template<class Type> struct inter_section
262 : public identity_based_inplace_combine<Type>
264 typedef typename boost::mpl::
265 if_<has_set_semantics<Type>,
266 icl::inplace_et<Type>,
267 icl::inplace_plus<Type>
271 void operator()(Type& object, const Type& operand)const
273 type()(object, operand);
277 //--------------------------------------------------------------------------
279 //--------------------------------------------------------------------------
280 template<class Functor> struct inverse;
283 struct inverse<icl::inplace_plus<Type> >
284 { typedef icl::inplace_minus<Type> type; };
287 struct inverse<icl::inplace_minus<Type> >
288 { typedef icl::inplace_plus<Type> type; };
291 struct inverse<icl::inplace_bit_add<Type> >
292 { typedef icl::inplace_bit_subtract<Type> type; };
295 struct inverse<icl::inplace_bit_subtract<Type> >
296 { typedef icl::inplace_bit_add<Type> type; };
299 struct inverse<icl::inplace_et<Type> >
300 { typedef icl::inplace_caret<Type> type; };
303 struct inverse<icl::inplace_caret<Type> >
304 { typedef icl::inplace_et<Type> type; };
307 struct inverse<icl::inplace_bit_and<Type> >
308 { typedef icl::inplace_bit_xor<Type> type; };
311 struct inverse<icl::inplace_bit_xor<Type> >
312 { typedef icl::inplace_bit_and<Type> type; };
315 struct inverse<icl::inplace_star<Type> >
316 { typedef icl::inplace_slash<Type> type; };
319 struct inverse<icl::inplace_slash<Type> >
320 { typedef icl::inplace_star<Type> type; };
323 struct inverse<icl::inplace_max<Type> >
324 { typedef icl::inplace_min<Type> type; };
327 struct inverse<icl::inplace_min<Type> >
328 { typedef icl::inplace_max<Type> type; };
331 struct inverse<icl::inplace_identity<Type> >
332 { typedef icl::inplace_erasure<Type> type; };
335 template<class Functor>
339 remove_reference<typename Functor::first_argument_type>::type argument_type;
340 typedef icl::inplace_erasure<argument_type> type;
344 //--------------------------------------------------------------------------
345 // Inverse inter_section functor
346 //--------------------------------------------------------------------------
348 struct inverse<icl::inter_section<Type> >
349 : public identity_based_inplace_combine<Type>
351 typedef typename boost::mpl::
352 if_<has_set_semantics<Type>,
353 icl::inplace_caret<Type>,
354 icl::inplace_minus<Type>
358 void operator()(Type& object, const Type& operand)const
360 type()(object, operand);
365 //--------------------------------------------------------------------------
366 // Positive or negative functor trait
367 //--------------------------------------------------------------------------
369 // A binary operation - is negative (or inverting) with respect to the
370 // neutral element iff it yields the inverse element if it is applied to the
373 // For a functor that wraps the inplace of op-assign version this is
377 // y = Functor::identity_element();
378 // Functor()(y, x); // y == inverse_of(x)
380 template<class Functor> struct is_negative;
382 template<class Functor>
385 typedef is_negative<Functor> type;
386 BOOST_STATIC_CONSTANT(bool, value = false);
390 struct is_negative<icl::inplace_minus<Type> >
392 typedef is_negative type;
393 BOOST_STATIC_CONSTANT(bool, value = true);
397 struct is_negative<icl::inplace_bit_subtract<Type> >
399 typedef is_negative type;
400 BOOST_STATIC_CONSTANT(bool, value = true);
403 //--------------------------------------------------------------------------
404 // Pro- or in-version functor
405 //--------------------------------------------------------------------------
406 template<class Combiner> struct conversion;
408 template<class Combiner>
411 typedef conversion<Combiner> type;
414 typename remove_reference<typename Combiner::first_argument_type
418 // The proversion of an op-assign functor o= lets the value unchanged
420 // Example += : (0 += x) == x
421 static argument_type proversion(const argument_type& value)
426 // The inversion of an op-assign functor o= inverts the value x
427 // to it's inverse element -x
429 // Example -= : (0 -= x) == -x
430 static argument_type inversion(const argument_type& value)
432 argument_type inverse = Combiner::identity_element();
433 Combiner()(inverse, value);
438 template<class Combiner> struct version : public conversion<Combiner>
440 typedef version<Combiner> type;
441 typedef conversion<Combiner> base_type;
442 typedef typename base_type::argument_type argument_type;
444 argument_type operator()(const argument_type& value)
445 { return base_type::proversion(value); }
448 template<>struct version<icl::inplace_minus<short > >{short operator()(short val){return -val;}};
449 template<>struct version<icl::inplace_minus<int > >{int operator()(int val){return -val;}};
450 template<>struct version<icl::inplace_minus<long > >{long operator()(long val){return -val;}};
451 template<>struct version<icl::inplace_minus<long long > >{long long operator()(long long val){return -val;}};
452 template<>struct version<icl::inplace_minus<float > >{float operator()(float val){return -val;}};
453 template<>struct version<icl::inplace_minus<double > >{double operator()(double val){return -val;}};
454 template<>struct version<icl::inplace_minus<long double> >{long double operator()(long double val){return -val;}};
457 struct version<icl::inplace_minus<Type> > : public conversion<icl::inplace_minus<Type> >
459 typedef version<icl::inplace_minus<Type> > type;
460 typedef conversion<icl::inplace_minus<Type> > base_type;
461 typedef typename base_type::argument_type argument_type;
463 Type operator()(const Type& value)
465 return base_type::inversion(value);
469 }} // namespace icl boost