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 = utility::static_eq<S1, typename ret_t::set_t>::value; \
00109 typedef typename utility::static_if<want_s1, S1, S2>::t ret_set_t; \
00110 const ret_set_t& s = utility::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