Vaucanson 1.4
|
00001 // element_ops.hxx: this file is part of the Vaucanson project. 00002 // 00003 // Vaucanson, a generic library for finite state machines. 00004 // 00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 The Vaucanson Group. 00006 // 00007 // This program is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU General Public License 00009 // as published by the Free Software Foundation; either version 2 00010 // of the License, or (at your option) any later version. 00011 // 00012 // The complete GNU General Public Licence Notice can be found as the 00013 // `COPYING' file in the root directory. 00014 // 00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file. 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 | Operator prototype forms | 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 | Standard delegation forms | 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 | Standard Boolean delegations | 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 | Standard arithmetical delegations | 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 /* Compute return Element type */ \ 00133 typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t; \ 00134 \ 00135 /* Compute return structural element from return Element type */ \ 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 /* Delegate */ \ 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 | Implementation of input and output delegations | 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 | Implementation of the negation delegation | 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 } // vcsn 00217 00218 00219 /*--------------------------------------. 00220 | Implementation of the swap delegation | 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 } // std 00257 00258 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX