00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef MLN_FUN_COMPOSITION_HH
00027 # define MLN_FUN_COMPOSITION_HH
00028
00029 # include <mln/fun/unary.hh>
00030 # include <mln/fun/binary.hh>
00031 # include <mln/fun/param.hh>
00032
00033 namespace mln
00034 {
00035
00036 namespace fun
00037 {
00038
00039 namespace internal
00040 {
00041
00042
00043 template <typename F, typename G>
00044 struct composition_param
00045 {
00046 composition_param(const F& f, const G& g) : f_(f), g_(g) {}
00047 composition_param() {}
00048
00049 F f_;
00050 G g_;
00051 };
00052
00053
00054 template <template <class> class CatF, typename F,
00055 template <class> class CatG, typename G>
00056 struct composition;
00057
00058 }
00059
00060 template <template <class> class CatF, typename F,
00061 template <class> class CatG, typename G>
00062 struct parameter< internal::composition<CatF, F, CatG, G> >
00063 {
00064 typedef internal::composition_param<F, G> param;
00065 };
00066
00067 namespace internal
00068 {
00069
00070
00071 template <typename F, typename G>
00072 struct composition<mln::Meta_Function_v2v, F, mln::Meta_Function_v2v, G>
00073 : mln::fun::unary< composition<mln::Meta_Function_v2v, F, mln::Meta_Function_v2v, G> >
00074 {
00075 typedef mln::fun::unary< composition<mln::Meta_Function_v2v, F, mln::Meta_Function_v2v, G> > super;
00076
00077 composition() {};
00078 composition(const composition_param<F, G>& p) : super(p) {};
00079
00080 typedef composition exact_type;
00081 };
00082
00083 template <typename F, typename G>
00084 struct composition<mln::Meta_Function_v2v, F, mln::Meta_Function_vv2v, G>
00085 : mln::fun::binary< composition<mln::Meta_Function_v2v, F, mln::Meta_Function_vv2v, G> >
00086 {
00087 typedef mln::fun::binary< composition<mln::Meta_Function_v2v, F, mln::Meta_Function_vv2v, G> > super;
00088
00089 composition() {};
00090 composition(const composition_param<F, G>& p) : super(p) {};
00091
00092 typedef composition exact_type;
00093 };
00094
00095
00096 template <typename F, typename G>
00097 struct composition<mln::Meta_Function_v2v, F, mln::Function_v2v, G>
00098 {
00099 typedef mln::fun::spe::unary< composition<mln::Meta_Function_v2v, F, mln::Function_vv2v, G>, typename G::argument> exact_type;
00100 };
00101
00102 template <typename F, typename G>
00103 struct composition<mln::Meta_Function_v2v, F, mln::Function_vv2v, G>
00104 {
00105 typedef mln::fun::spe::binary< composition<mln::Meta_Function_v2v, F, mln::Function_vv2v, G>,
00106 typename G::argument1, typename G::argument2> exact_type;
00107 };
00108
00109
00110 template <bool has_lvalue, typename F, typename F_spe, typename G, typename G_spe>
00111 struct composition_unary_impl_helper;
00112
00113 template <typename F, typename F_spe, typename G, typename G_spe>
00114 struct composition_unary_impl_helper<false, F, F_spe, G, G_spe>
00115 {
00116 typedef typename G_spe::argument argument;
00117 typedef typename F_spe::result result;
00118 typedef composition_param<F, G> param;
00119
00120 static result read(const param& p, const argument& x)
00121 {
00122 return p.f_(p.g_(x));
00123 }
00124 };
00125
00126 template <typename F, typename F_spe, typename G, typename G_spe>
00127 struct composition_unary_impl_helper<true, F, F_spe, G, G_spe>
00128 : composition_unary_impl_helper<false, F, F_spe, G, G_spe>
00129 {
00130 typedef composition_unary_impl_helper<false, F, F_spe, G, G_spe> super;
00131 typedef typename G_spe::lvalue lvalue;
00132
00133 composition_unary_impl_helper() {}
00134 composition_unary_impl_helper(const typename super::param& p) : super(p) {}
00135
00136 static void write(const typename super::param& p, lvalue l, const typename super::result& x)
00137 {
00138 typename G_spe::result r(p.g_(l));
00139
00140 p.f_.set(r, x);
00141 p.g_.set(l, r);
00142 }
00143 };
00144
00145 template <typename F, typename F_spe, typename G, typename G_spe>
00146 struct composition_unary_impl
00147 : composition_unary_impl_helper<mln_trait_fun_is_assignable_(G_spe)::value, F, F_spe, G, G_spe>
00148 {
00149 typedef composition_unary_impl_helper<mln_trait_fun_is_assignable_(G_spe)::value, F, F_spe, G, G_spe> super;
00150
00151 composition_unary_impl() {}
00152 composition_unary_impl(const typename super::param& p) : super(p) {}
00153 };
00154
00155 template <typename F, typename F_spe, typename G, typename G_spe>
00156 struct composition_binary_impl
00157 {
00158 typedef typename G_spe::argument1 argument1;
00159 typedef typename G_spe::argument2 argument2;
00160 typedef typename F_spe::result result;
00161 typedef composition_param<F, G> param;
00162
00163 static result read(const param& p, const argument1& a, const argument2& b)
00164 {
00165 return p.f_(p.g_(a, b));
00166 }
00167 };
00168
00169 }
00170
00171 }
00172
00173 namespace trait
00174 {
00175
00176 namespace next
00177 {
00178
00179 template <typename F, typename G, typename T>
00180 struct set_precise_unary_<mln::fun::internal::composition<mln::Meta_Function_v2v, F, mln::Meta_Function_v2v, G>, T>
00181 {
00182 typedef typename G::template with<T>::ret G_fun;
00183 typedef typename F::template with<typename G_fun::result>::ret F_fun;
00184
00185 typedef mln::fun::internal::composition_unary_impl<F, F_fun, G, G_fun> ret;
00186 };
00187
00188 template <typename F, typename G, typename T1, typename T2>
00189 struct set_precise_binary_<mln::fun::internal::composition<mln::Meta_Function_v2v, F, mln::Meta_Function_vv2v, G>, T1, T2>
00190 {
00191 typedef typename G::template with<T1, T2>::ret G_fun;
00192 typedef typename F::template with<typename G_fun::result>::ret F_fun;
00193
00194 typedef mln::fun::internal::composition_binary_impl<F, F_fun, G, G_fun> ret;
00195 };
00196
00197 template <typename F, typename G>
00198 struct set_precise_unary_<mln::fun::internal::composition<mln::Meta_Function_v2v, F, mln::Function_v2v, G>,
00199 typename G::argument>
00200 {
00201 typedef typename F::template with<typename G::result>::ret F_fun;
00202
00203 typedef mln::fun::internal::composition_unary_impl<F, F_fun, G, G> ret;
00204 };
00205
00206 template <typename F, typename G>
00207 struct set_precise_binary_<mln::fun::internal::composition<mln::Meta_Function_v2v, F, mln::Meta_Function_vv2v, G>,
00208 typename G::argument1, typename G::argument2>
00209 {
00210 typedef typename F::template with<typename G::result>::ret F_fun;
00211
00212 typedef mln::fun::internal::composition_binary_impl<F, F_fun, G, G> ret;
00213 };
00214
00215 }
00216
00217 }
00218
00219 }
00220
00221 #endif // ! MLN_FUN_COMPOSITION_HH