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 static \
00035 Ret \
00036 operator Op(const Element<S1, T1>& e1, \
00037 const Element<S2, T2>& e2)
00038
00039 #define ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, Ret) \
00040 template<typename S1, typename T1, typename T2> \
00041 static \
00042 Ret \
00043 operator Op(const Element<S1, T1>& e1, const T2& e2)
00044
00045 #define ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, Ret) \
00046 template<typename T1, typename S2, typename T2> \
00047 static \
00048 Ret \
00049 operator Op(const T1& e1, const Element<S2, T2>& e2)
00050
00051
00052
00053
00054
00055 #define DELEGATE_SYM(OpName) \
00056 return op_ ## OpName(e1.structure(), e2.structure(), e1.value(), e2.value())
00057
00058 #define DELEGATE_LEFT_FOREIGN(OpName) \
00059 return op_ ## OpName(e1.structure(), \
00060 e1.value(), \
00061 op_convert(e1.structure(), SELECT(T1), e2))
00062
00063 #define DELEGATE_RIGHT_FOREIGN(OpName) \
00064 return op_ ## OpName(e2.structure(), \
00065 op_convert(e2.structure(), SELECT(T2), e1), \
00066 e2.value())
00067
00068
00069
00070
00071
00072
00073 #define BOOLEAN_DELEGATION(Op, OpName) \
00074 ELEMENT_OP_PROTO_SYM(Op, bool) \
00075 { \
00076 DELEGATE_SYM(OpName); \
00077 } \
00078 \
00079 ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) \
00080 { \
00081 DELEGATE_LEFT_FOREIGN(OpName); \
00082 } \
00083 \
00084 ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) \
00085 { \
00086 DELEGATE_RIGHT_FOREIGN(OpName); \
00087 }
00088
00089 BOOLEAN_DELEGATION(==, eq)
00090 BOOLEAN_DELEGATION(<, lt)
00091 #undef BOOLEAN_DELEGATION
00092
00093 #define BOOLEAN_CANONICAL_DELEGATION(Op, Not, E1, Del, E2) \
00094 ELEMENT_OP_PROTO_SYM(Op, bool) \
00095 { \
00096 return Not (e ## E1 Del e ## E2); \
00097 } \
00098 \
00099 ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) \
00100 { \
00101 return Not (e ## E1 Del e ## E2); \
00102 } \
00103 \
00104 ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) \
00105 { \
00106 return Not (e ## E1 Del e ## E2); \
00107 }
00108
00109 BOOLEAN_CANONICAL_DELEGATION(!=, !, 1, ==, 2)
00110 BOOLEAN_CANONICAL_DELEGATION(> , , 2, <, 1)
00111 BOOLEAN_CANONICAL_DELEGATION(>=, !, 1, <, 2)
00112 BOOLEAN_CANONICAL_DELEGATION(<=, !, 2, <, 1)
00113 #undef BOOLEAN_CANONICAL_DELEGATION
00114
00115 #undef ELEMENT_PROTO_SYM
00116 #undef ELEMENT_PROTO_LEFT_FOREIGN
00117 #undef ELEMENT_PROTO_RIGHT_FOREIGN
00118 #undef DELEGATE_SYM
00119 #undef DELEGATE_LEFT_FOREIGN
00120 #undef DELEGATE_RIGHT_FOREIGN
00121
00122
00123
00124
00125
00126 #define ELEMENT_OPERATOR(Op, HookName) \
00127 template<typename S1, typename T1, typename S2, typename T2> \
00128 static \
00129 typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t \
00130 operator Op(const Element<S1, T1>& e1, const Element<S2, T2>& e2) \
00131 { \
00132 \
00133 typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t; \
00134 \
00135 \
00136 const bool want_s1 = misc::static_eq<S1, typename ret_t::set_t>::value; \
00137 typedef typename misc::static_if<want_s1, S1, S2>::t ret_set_t; \
00138 const ret_set_t& s = misc::static_if<want_s1, const S1, const S2>:: \
00139 choose(e1.structure(), e2.structure()); \
00140 \
00141 \
00142 return Element<ret_set_t, typename ret_t::value_t> \
00143 (s, op_##HookName(e1.structure(), \
00144 e2.structure(), \
00145 e1.value(), \
00146 e2.value())); \
00147 } \
00148 \
00149 template<typename S, typename T, typename U> \
00150 static \
00151 Element<S, T> \
00152 operator Op(const Element<S, T>& e, const U& v) \
00153 { \
00154 return Element<S, T> (e.structure(), \
00155 op_##HookName(e.structure(), \
00156 e.value(), \
00157 op_convert(e.structure(), \
00158 SELECT(T), v))); \
00159 } \
00160 \
00161 template<typename U, typename S, typename T> \
00162 static \
00163 Element<S, T> \
00164 operator Op(const U& v, const Element<S, T>& e) \
00165 { \
00166 return Element<S, T> (e.structure(), \
00167 op_ ## HookName(e.structure(), \
00168 op_convert(e.structure(), \
00169 SELECT(T), v), \
00170 e.value())); \
00171 }
00172
00173 ELEMENT_OPERATOR(+, add)
00174 ELEMENT_OPERATOR(-, sub)
00175 ELEMENT_OPERATOR(*, mul)
00176 ELEMENT_OPERATOR(/, div)
00177 ELEMENT_OPERATOR(%, mod)
00178
00179 #undef ELEMENT_OPERATOR
00180
00181
00182
00183
00184
00185 template<typename St, typename S, typename T>
00186 static
00187 St&
00188 operator << (St& s, const Element<S, T>& e)
00189 {
00190 return op_rout(e.structure(), s, e.value());
00191 }
00192
00193 template<typename St, typename S, typename T>
00194 static
00195 St&
00196 operator >> (St& s, Element<S, T>& e)
00197 {
00198 S structure = e.structure();
00199 op_rin(structure, s, e.value());
00200 e.attach(structure);
00201 return s;
00202 }
00203
00204
00205
00206
00207
00208 template<typename S, typename T>
00209 static
00210 Element<S, T>
00211 operator-(const Element<S, T>& e)
00212 {
00213 return Element<S, T>(e.structure(), op_neg(e.structure(), e.value()));
00214 }
00215
00216 }
00217
00218
00219
00220
00221
00222
00223 namespace std
00224 {
00225 template<typename S, typename T1, typename T2>
00226 void
00227 swap(vcsn::Element<S, T1>& e1,
00228 vcsn::Element<S, T2>& e2)
00229 {
00230 assertion(&e1.structure() == &e2.structure());
00231 op_swap(e1.structure(), e1.value(), e2.value());
00232 }
00233
00234 template<typename S, typename T>
00235 void
00236 swap(vcsn::Element<S, T>& e1,
00237 vcsn::Element<S, T>& e2)
00238 {
00239 assertion(&e1.structure() == &e2.structure());
00240 op_swap(e1.structure(), e1.value(), e2.value());
00241 }
00242
00243 template<typename S, typename T>
00244 void
00245 swap(vcsn::Element<S, T>& e1, T& v2)
00246 {
00247 op_swap(e1.structure(), e1.value(), v2);
00248 }
00249
00250 template<typename T, typename S>
00251 void
00252 swap(T& v1, vcsn::Element<S, T>& e2)
00253 {
00254 op_swap(e2.structure(), v1, e2.value());
00255 }
00256 }
00257
00258 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX