00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 #ifndef VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
00018 # define VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
00019 
00020 # include <vaucanson/design_pattern/element_ops.hh>
00021 
00022 # include <vaucanson/misc/selectors.hh>
00023 # include <vaucanson/misc/static.hh>
00024 # include <vaucanson/misc/unique.hh>
00025 
00026 namespace vcsn {
00027 
00028   
00029 
00030 
00031 
00032 #define ELEMENT_OP_PROTO_SYM(Op, Ret)                           \
00033 template<typename S1, typename T1, typename S2, typename T2>    \
00034 Ret operator Op(const Element<S1, T1>& x1,                      \
00035                 const Element<S2, T2>& x2)
00036 
00037 #define ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, Ret)                  \
00038 template<typename S1, typename T1, typename T2>                 \
00039 Ret operator Op(const Element<S1, T1>& x1, const T2& x2)
00040 
00041 #define ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, Ret)                 \
00042 template<typename T1, typename S2, typename T2>                 \
00043 Ret operator Op(const T1& x1, const Element<S2, T2>& x2)
00044 
00045   
00046 
00047 
00048 
00049 #define DELEGATE_SYM(OpName) \
00050  return op_ ## OpName(x1.structure(), x2.structure(), x1.value(), x2.value())
00051 
00052 #define DELEGATE_LEFT_FOREIGN(OpName) \
00053   return op_ ## OpName(x1.structure(),                                  \
00054                        x1.value(),                                      \
00055                        op_convert(x1.structure(), SELECT(T1), x2))
00056 
00057 #define DELEGATE_RIGHT_FOREIGN(OpName) \
00058   return op_ ## OpName(x2.structure(),                                  \
00059                        op_convert(x2.structure(), SELECT(T2), x1),      \
00060                        x2.value())
00061 
00062 
00063   
00064 
00065 
00066 
00067 #define BOOLEAN_DELEGATION(Op, OpName)                                          \
00068   ELEMENT_OP_PROTO_SYM(Op, bool) { DELEGATE_SYM(OpName); }                      \
00069   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) { DELEGATE_LEFT_FOREIGN(OpName); }    \
00070   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) { DELEGATE_RIGHT_FOREIGN(OpName); }
00071 
00072   BOOLEAN_DELEGATION(==, eq)
00073   BOOLEAN_DELEGATION(<, lt)
00074 #undef BOOLEAN_DELEGATION
00075 
00076 #define BOOLEAN_CANONICAL_DELEGATION(Op, Not, X1, Del, X2)                              \
00077   ELEMENT_OP_PROTO_SYM(Op, bool) { return Not (x ## X1 Del x ## X2); }                  \
00078   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) { return Not (x ## X1 Del x ## X2); }         \
00079   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) { return Not (x ## X1 Del x ## X2); }
00080 
00081   BOOLEAN_CANONICAL_DELEGATION(!=, !, 1, ==, 2)
00082   BOOLEAN_CANONICAL_DELEGATION(> ,  , 2, <, 1)
00083   BOOLEAN_CANONICAL_DELEGATION(>=, !, 1, <, 2)
00084   BOOLEAN_CANONICAL_DELEGATION(<=, !, 2, <, 1)
00085 #undef BOOLEAN_CANONICAL_DELEGATION
00086 
00087 #undef ELEMENT_PROTO_SYM
00088 #undef ELEMENT_PROTO_LEFT_FOREIGN
00089 #undef ELEMENT_PROTO_RIGHT_FOREIGN
00090 #undef DELEGATE_SYM
00091 #undef DELEGATE_LEFT_FOREIGN
00092 #undef DELEGATE_RIGHT_FOREIGN
00093 
00094     
00095 
00096 
00097 
00098 #define ELEMENT_OPERATOR(Op, HookName)                                                  \
00099 template<typename S1, typename T1, typename S2, typename T2>                            \
00100 static                                                                          \
00101 typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t                                  \
00102 operator Op(const Element<S1, T1>& e1, const Element<S2, T2>& e2)                       \
00103 {                                                                                       \
00104                                                        \
00105   typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t;                 \
00106                                                                                         \
00107                         \
00108   const bool want_s1 = misc::static_eq<S1, typename ret_t::set_t>::value;               \
00109   typedef typename misc::static_if<want_s1, S1, S2>::t ret_set_t;                       \
00110   const ret_set_t& s = misc::static_if<want_s1, const S1, const S2>::     \
00111     choose(e1.structure(), e2.structure());                                  \
00112                                                                                         \
00113                                                                           \
00114   return Element<ret_set_t, typename ret_t::value_t>                                    \
00115     (s, op_##HookName(e1.structure(),                                        \
00116                       e2.structure(),                                        \
00117                       e1.value(),                                            \
00118                       e2.value()));                                          \
00119 }                                                                                       \
00120                                                                                         \
00121 template<typename S, typename T, typename U>                                            \
00122 static Element<S, T>                                                            \
00123 operator Op(const Element<S, T>& e, const U& v)                                         \
00124 {                                                                                       \
00125   return Element<S, T> (e.structure(),                                       \
00126                         op_##HookName(e.structure(),                         \
00127                                       e.value(),                                        \
00128                                       op_convert(e.structure(),              \
00129                                                  SELECT(T), v)));            \
00130 }                                                                                       \
00131                                                                                         \
00132 template<typename U, typename S, typename T>                                            \
00133 static Element<S, T>                                                            \
00134 operator Op(const U& v, const Element<S, T>& e)                                         \
00135 {                                                                                       \
00136   return Element<S, T> (e.structure(),                                       \
00137                         op_ ## HookName(e.structure(),                       \
00138                                         op_convert(e.structure(),            \
00139                                                    SELECT(T), v),            \
00140                                         e.value()));                                    \
00141 }
00142 
00143 ELEMENT_OPERATOR(+, add)
00144 ELEMENT_OPERATOR(-, sub)
00145 ELEMENT_OPERATOR(*, mul)
00146 ELEMENT_OPERATOR(/, div)
00147 ELEMENT_OPERATOR(%, mod)
00148 
00149 #undef ELEMENT_OPERATOR
00150 
00151 
00152 
00153 
00154 
00155 template<typename St, typename S, typename T>
00156 static St&
00157 operator << (St& s, const Element<S, T>& e)
00158 {
00159   return op_rout(e.structure(), s, e.value());
00160 }
00161 
00162 template<typename St, typename S, typename T>
00163 static St&
00164 operator >> (St& s, Element<S, T>& e)
00165 {
00166   S structure = e.structure();
00167   op_rin(structure, s, e.value());
00168   e.attach(structure);
00169   return s;
00170 }
00171 
00172 
00173 
00174 
00175 
00176 template<typename S, typename T>
00177 static Element<S, T>
00178 operator-(const Element<S, T>& e)
00179 {
00180   return Element<S, T>(e.structure(), op_neg(e.structure(), e.value()));
00181 }
00182 
00183 } 
00184 
00185 
00186 
00187 
00188 
00189 
00190 namespace std
00191 {
00192   template<typename S, typename T1, typename T2>
00193   void swap(vcsn::Element<S, T1>& e1,
00194             vcsn::Element<S, T2>& e2)
00195   {
00196     assertion(&e1.structure() == &e2.structure());
00197     op_swap(e1.structure(), e1.value(), e2.value());
00198   }
00199 
00200   template<typename S, typename T>
00201   void swap(vcsn::Element<S, T>& e1, T& v2)
00202   {
00203     op_swap(e1.structure(), e1.value(), v2);
00204   }
00205 
00206   template<typename T, typename S>
00207   void swap(T& v1, vcsn::Element<S, T>& e2)
00208   {
00209     op_swap(e2.structure(), v1, e2.value());
00210   }
00211 } 
00212 
00213 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX