ivl 679
ivl/details/core/ivl_func/ivl_func.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 #ifndef IVL_CORE_DETAILS_IVL_FUNC_IVL_FUNC_HPP
00025 #define IVL_CORE_DETAILS_IVL_FUNC_IVL_FUNC_HPP
00026 
00027 namespace ivl {
00028 
00029 namespace convert {
00030 
00031 struct dd { };
00032 struct dl { };
00033 struct df { };
00034 struct ff { };
00035 
00036 struct convd { };
00037 struct convl { };
00038 struct convf { };
00039 
00040 template<class C> struct get_out { typedef convd type; };
00041 template<> struct get_out<ff> { typedef convf type; };
00042 
00043 } /* namespace convert */
00044 
00045 template <class IMPL, class TPL, class OUTCONV>
00046 struct ivl_func_rvalue
00047 :
00048 public internal::tuple_rvalue<ivl_func_rvalue<IMPL, TPL, OUTCONV> >
00049 {
00050         //const TPL&
00051         TPL tpl;
00052         typedef typename types::bare_type<TPL>::type tp;
00053 
00054         /*
00055         template<class T>
00056         ivl_func_rvalue(const T& t) : tpl(t) { }
00057         */
00058         ivl_func_rvalue(TPL ts) : tpl(ts) { }
00059 
00060         ivl_func_rvalue(
00061                 typename tp::t1 v1 = types::skip(),
00062                 typename tp::t2 v2 = types::skip(),
00063                 typename tp::t3 v3 = types::skip(),
00064                 typename tp::t4 v4 = types::skip(),
00065                 typename tp::t5 v5 = types::skip(),
00066                 typename tp::t6 v6 = types::skip(),
00067                 typename tp::t7 v7 = types::skip(),
00068                 typename tp::t8 v8 = types::skip(),
00069                 typename tp::t9 v9 = types::skip(),
00070                 typename tp::t10 v10 = types::skip())
00071                         : tpl(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)
00072                 {}
00073 
00074         template <class TUP>
00075         inline
00076         void tuple_output(TUP& tup) const
00077         {
00078                 IMPL imp;
00079                 internal::apply_tuple(internal::tplsjoin(tup, tpl), imp);
00080         }
00081 
00082         template <class TUP>
00083         inline
00084         void tuple_output(const TUP& tup) const
00085         {
00086                 IMPL imp;
00087                 //imp.t_operate(internal::tplsjoin(tup, tpl));
00088                 internal::apply_tuple(internal::tplsjoin(tup, tpl), imp);
00089         }
00090 /*
00091         ivl_func_rvalue(const ivl_func_rvalue& oo) :tpl(oo.tpl)
00092         {
00093                 std::cout << "ACOPY!!!!!!!!!!!!!!!!!!\n";
00094         }
00095 */
00096         //TODO:necessary?
00097         /*
00098         template <class T1>
00099         inline
00100         void output(T1& t1) const
00101         {
00102                 IMPL imp;
00103                 imp.t_operate(internal::tplsjoin(
00104                         internal::reftpl(t1), tpl));
00105         }
00106 
00107         template <class T1, class T2>
00108         inline
00109         void output(T1& t1, T2& t2) const
00110         {
00111                 IMPL imp;
00112                 imp.t_operate(internal::tplsjoin(
00113                         internal::reftpl(t1, t2), tpl));
00114         }
00115 
00116         template <class T1, class T2, class T3>
00117         inline
00118         void output(T1& t1, T2& t2, T3& t3) const
00119         {
00120                 IMPL imp;
00121                 imp.t_operate(internal::tplsjoin(
00122                         internal::reftpl(t1, t2, t3), tpl));
00123         }
00124 
00125         template <class T1, class T2, class T3, class T4>
00126         inline
00127         void output(T1& t1, T2& t2, T3& t3, T4& t4) const
00128         {
00129                 IMPL imp;
00130                 imp.t_operate(internal::tplsjoin(
00131                         internal::reftpl(t1, t2, t3, t4), tpl));
00132         }
00133 
00134         template <class T1, class T2, class T3, class T4, class T5>
00135         inline
00136         void output(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
00137         {
00138                 IMPL imp;
00139                 imp.t_operate(internal::tplsjoin(
00140                         internal::reftpl(t1, t2, t3, t4, t5), tpl));
00141         }
00142 
00143         template <class T1, class T2, class T3, class T4, class T5, class T6>
00144         inline
00145         void output(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) const
00146         {
00147                 IMPL imp;
00148                 imp.t_operate(internal::tplsjoin(
00149                         internal::reftpl(t1, t2, t3, t4, t5, t6), tpl));
00150         }
00151 
00152         template <class T1, class T2, class T3, class T4, class T5, class T6,
00153                 class T7>
00154         inline
00155         void output(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) const
00156         {
00157                 IMPL imp;
00158                 imp.t_operate(internal::tplsjoin(
00159                         internal::reftpl(t1, t2, t3, t4, t5, t6, t7), tpl));
00160         }
00161         */
00162 
00163 };
00164 
00165 // ----
00166 
00167 template <class IMPL, class CONV>
00168 struct ivl_func_lcall
00169 {
00170         template<class TPL>
00171         inline
00172         ivl_func_rvalue<IMPL, const TPL&,
00173                 typename convert::get_out<CONV>::type>
00174                 operator[](const TPL& t) { return t; }
00175 
00176 
00177 
00178 
00179         inline
00180         ivl_func_rvalue<IMPL,
00181                 internal::tuple<>,
00182                 typename convert::get_out<CONV>::type>
00183                 operator()()
00184         {
00185                 return internal::tuple<>();
00186         }
00187 
00188         template<class T1>
00189         inline
00190         ivl_func_rvalue<IMPL,
00191                 internal::tuple<const T1&>,
00192                 typename convert::get_out<CONV>::type>
00193                 operator()(const T1& t1)
00194         {
00195                 return ivl_func_rvalue<IMPL,
00196                 internal::tuple<const T1&>,
00197                 typename convert::get_out<CONV>::type>(t1);
00198         }
00199 
00200         template<class T1, class T2>
00201         inline
00202         ivl_func_rvalue<IMPL,
00203                 internal::tuple<const T1&, const T2&>,
00204                 typename convert::get_out<CONV>::type>
00205                 operator()(const T1& t1, const T2& t2)
00206         {
00207                 return ivl_func_rvalue<IMPL,
00208                 internal::tuple<const T1&, const T2&>,
00209                 typename convert::get_out<CONV>::type>(t1, t2);
00210         }
00211 
00212         template<class T1, class T2, class T3>
00213         inline
00214         ivl_func_rvalue<IMPL,
00215                 internal::tuple<const T1&, const T2&, const T3&>,
00216                 typename convert::get_out<CONV>::type>
00217                 operator()(const T1& t1, const T2& t2, const T3& t3)
00218         {
00219                 return ivl_func_rvalue<IMPL,
00220                 internal::tuple<const T1&, const T2&, const T3&>,
00221                 typename convert::get_out<CONV>::type>(t1, t2, t3);
00222         }
00223 
00224         template<class T1, class T2, class T3, class T4>
00225         inline
00226         ivl_func_rvalue<IMPL,
00227                 internal::tuple<const T1&, const T2&, const T3&, const T4&>,
00228                 typename convert::get_out<CONV>::type>
00229                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
00230         {
00231                 return ivl_func_rvalue<IMPL,
00232                 internal::tuple<const T1&, const T2&, const T3&, const T4&>,
00233                 typename convert::get_out<CONV>::type>(t1, t2, t3, t4);
00234         }
00235 
00236         template<class T1, class T2, class T3, class T4, class T5>
00237         inline
00238         ivl_func_rvalue<IMPL,
00239                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00240                                                 const T5&>,
00241                 typename convert::get_out<CONV>::type>
00242                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00243                                         const T5& t5)
00244         {
00245                 return ivl_func_rvalue<IMPL,
00246                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00247                                                 const T5&>,
00248                 typename convert::get_out<CONV>::type>(t1, t2, t3, t4, t5);
00249         }
00250 
00251         template<class T1, class T2, class T3, class T4, class T5, class T6>
00252         inline
00253         ivl_func_rvalue<IMPL,
00254                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00255                                                 const T5&, const T6&>,
00256                 typename convert::get_out<CONV>::type>
00257                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00258                                         const T5& t5, const T6& t6)
00259         {
00260                 return ivl_func_rvalue<IMPL,
00261                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00262                                                 const T5&, const T6&>,
00263                 typename convert::get_out<CONV>::type>(t1, t2, t3, t4, t5, t6);
00264         }
00265 
00266         template<class T1, class T2, class T3, class T4, class T5, class T6,
00267                         class T7>
00268         inline
00269         ivl_func_rvalue<IMPL,
00270                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00271                                                 const T5&, const T6&, const T7&>,
00272                 typename convert::get_out<CONV>::type>
00273                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00274                                         const T5& t5, const T6& t6, const T7& t7)
00275         {
00276                 return ivl_func_rvalue<IMPL,
00277                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00278                                                 const T5&, const T6&, const T7&>,
00279                 typename convert::get_out<CONV>::type>(t1, t2, t3, t4, t5, t6, t7);
00280         }
00281 
00282 
00283 /*
00284         inline
00285         ivl_func_rvalue<IMPL,
00286                 internal::tuple<>,
00287                 typename convert::get_out<CONV>::type>
00288                 operator()()
00289         {
00290                 return internal::tuple<>();
00291         }
00292 
00293         template<class T1>
00294         inline
00295         ivl_func_rvalue<IMPL,
00296                 internal::tuple<const T1&>,
00297                 typename convert::get_out<CONV>::type>
00298                 operator()(const T1& t1)
00299         {
00300                 return internal::reftpl(t1);
00301         }
00302 
00303         template<class T1, class T2>
00304         inline
00305         ivl_func_rvalue<IMPL,
00306                 internal::tuple<const T1&, const T2&>,
00307                 typename convert::get_out<CONV>::type>
00308                 operator()(const T1& t1, const T2& t2)
00309         {
00310                 return internal::reftpl(t1, t2);
00311         }
00312 
00313         template<class T1, class T2, class T3>
00314         inline
00315         ivl_func_rvalue<IMPL,
00316                 internal::tuple<const T1&, const T2&, const T3&>,
00317                 typename convert::get_out<CONV>::type>
00318                 operator()(const T1& t1, const T2& t2, const T3& t3)
00319         {
00320                 return internal::reftpl(t1, t2, t3);
00321         }
00322 
00323         template<class T1, class T2, class T3, class T4>
00324         inline
00325         ivl_func_rvalue<IMPL,
00326                 internal::tuple<const T1&, const T2&, const T3&, const T4&>,
00327                 typename convert::get_out<CONV>::type>
00328                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
00329         {
00330                 return internal::reftpl(t1, t2, t3, t4);
00331         }
00332 
00333         template<class T1, class T2, class T3, class T4, class T5>
00334         inline
00335         ivl_func_rvalue<IMPL,
00336                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00337                                                 const T5&>,
00338                 typename convert::get_out<CONV>::type>
00339                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00340                                         const T5& t5)
00341         {
00342                 return internal::reftpl(t1, t2, t3, t4, t5);
00343         }
00344 
00345         template<class T1, class T2, class T3, class T4, class T5, class T6>
00346         inline
00347         ivl_func_rvalue<IMPL,
00348                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00349                                                 const T5&, const T6&>,
00350                 typename convert::get_out<CONV>::type>
00351                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00352                                         const T5& t5, const T6& t6)
00353         {
00354                 return internal::reftpl(t1, t2, t3, t4, t5, t6);
00355         }
00356 
00357         template<class T1, class T2, class T3, class T4, class T5, class T6,
00358                         class T7>
00359         inline
00360         ivl_func_rvalue<IMPL,
00361                 internal::tuple<const T1&, const T2&, const T3&, const T4&,
00362                                                 const T5&, const T6&, const T7&>,
00363                 typename convert::get_out<CONV>::type>
00364                 operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00365                                         const T5& t5, const T6& t6, const T7& t7)
00366         {
00367                 return internal::reftpl(t1, t2, t3, t4, t5, t6, t7);
00368         }
00369         */
00370 };
00371 
00372 // ----
00373 
00374 template <class DERIVED, class CONV = convert::ff>
00375 struct ivl_func
00376 {
00377 private:
00378         DERIVED& derived() { return static_cast<DERIVED&>(*this); }
00379 public:
00380         typedef ivl_func_lcall<DERIVED, CONV> lcall_type;
00381 
00382         lcall_type operator++(int) { return lcall_type(); }
00383 
00384 /*
00385 //TODO: necessary?
00386         template<int N, class T>
00387         inline void t_operate(const internal::tuple_base<N, T>& tpl)
00388         {
00389                 //TODO: fix
00390                 //the fix should probably be in the tuple value access.
00391                 //if any fix.
00392                 //otherwise, construct a tuple object when passing here
00393                 //and get an actual reference.
00394                 //other option, skip this part anyway to also avoid using.
00395                 T& t(const_cast<T&>(tpl.derived()));
00396                 internal::apply_tuple(t, derived());
00397         }
00398 */
00399 /*
00400         template<class T>
00401         inline void operate(internal::tuple_base<1, T> tpl)
00402         {
00403                 T& t(tpl.derived());
00404                 derived().operate(t.v1);
00405         }
00406 
00407         template<class T>
00408         inline void operate(internal::tuple_base<2, T> tpl)
00409         {
00410                 T& t(tpl.derived());
00411                 derived().operate(t.v1, t.v2);
00412         }
00413 
00414         template<class T>
00415         inline void operate(internal::tuple_base<3, T> tpl)
00416         {
00417                 T& t(tpl.derived());
00418                 derived().operate(t.v1, t.v2, t.v3);
00419         }
00420 
00421         template<class T>
00422         inline void operate(internal::tuple_base<4, T> tpl)
00423         {
00424                 T& t(tpl.derived());
00425                 derived().operate(t.v1, t.v2, t.v3, t.v4);
00426         }
00427 
00428         template<class T>
00429         inline void operate(internal::tuple_base<5, T> tpl)
00430         {
00431                 T& t(tpl.derived());
00432                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5);
00433         }
00434 
00435         template<class T>
00436         inline void operate(internal::tuple_base<6, T> tpl)
00437         {
00438                 T& t(tpl.derived());
00439                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5, t.v6);
00440         }
00441 
00442         template<class T>
00443         inline void operate(internal::tuple_base<7, T> tpl)
00444         {
00445                 T& t(tpl.derived());
00446                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5, t.v6, t.v7);
00447         }
00448 
00449         template<class T>
00450         inline void operate(internal::tuple_base<8, T> tpl)
00451         {
00452                 T& t(tpl.derived());
00453                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5, t.v6, t.v7, t.v8);
00454         }
00455 
00456         template<class T>
00457         inline void operate(internal::tuple_base<9, T> tpl)
00458         {
00459                 T& t(tpl.derived());
00460                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5, t.v6, t.v7, t.v8, t.v9);
00461         }
00462 
00463         template<class T>
00464         inline void operate(internal::tuple_base<10, T> tpl)
00465         {
00466                 T& t(tpl.derived());
00467                 derived().operate(t.v1, t.v2, t.v3, t.v4, t.v5, t.v6, t.v7, t.v8, t.v9,
00468                                                         t.v10);
00469         }
00470 */
00471         // ---------------------------------------------------------------------
00472 
00473         template <class RT, class T1>
00474         RT simple(const T1& t1)
00475         {
00476                 RT r = derived()++(t1);
00477                 return r;
00478         }
00479 
00480         template <class RT, class T1, class T2>
00481         RT simple(const T1& t1, const T2& t2)
00482         {
00483                 RT r = derived()++(t1, t2);
00484                 return r;
00485         }
00486 
00487         template <class RT, class T1, class T2, class T3>
00488         RT simple(const T1& t1, const T2& t2, const T3& t3)
00489         {
00490                 RT r = derived()++(t1, t2, t3);
00491                 return r;
00492         }
00493 
00494         template <class RT, class T1, class T2, class T3, class T4>
00495         RT simple(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
00496         {
00497                 RT r = derived()++(t1, t2, t3, t4);
00498                 return r;
00499         }
00500 
00501         template <class RT, class T1, class T2, class T3, class T4,
00502                 class T5>
00503         RT simple(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00504                                         const T5& t5)
00505         {
00506                 RT r = derived()++(t1, t2, t3, t4, t5);
00507                 return r;
00508         }
00509 
00510         template <class RT, class T1, class T2, class T3, class T4,
00511                 class T5, class T6>
00512         RT simple(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00513                                         const T5& t5, const T6& t6)
00514         {
00515                 RT r = derived()++(t1, t2, t3, t4, t5, t6);
00516                 return r;
00517         }
00518 
00519         template <class RT, class T1, class T2, class T3, class T4,
00520                 class T5, class T6, class T7>
00521         RT simple(const T1& t1, const T2& t2, const T3& t3, const T4& t4,
00522                                         const T5& t5, const T6& t6, const T7& t7)
00523         {
00524                 RT r = derived()++(t1, t2, t3, t4, t5, t6, t7);
00525                 return r;
00526         }
00527 
00528         // ---------------------------------------------------------------------
00529 
00530         template <
00531                 class R1, class R2 = types::skip, class R3 = types::skip,
00532                 class R4 = types::skip, class R5 = types::skip, class R6 = types::skip,
00533                 class R7 = types::skip, class R8 = types::skip, class R9 = types::skip,
00534                 class R10 = types::skip>
00535         struct call
00536         :
00537         public ret<R1, R2, R3, R4, R5, R6, R7, R8, R9, R10>
00538         {
00539                 template<class T1>
00540                 call(T1& t1)
00541                 {
00542                         DERIVED()++(t1).tuple_output(*this);
00543                 }
00544                 template<class T1, class T2>
00545                 call(T1& t1, T2& t2)
00546                 {
00547                         DERIVED()++(t1, t2).tuple_output(*this);
00548                 }
00549                 template<class T1, class T2, class T3>
00550                 call(T1& t1, T2& t2, T3& t3)
00551                 {
00552                         DERIVED()++(t1, t2, t3).tuple_output(*this);
00553                 }
00554         };
00555 };
00556 
00557 template <class DERIVED, class CONV>
00558 template <class R1>
00559 struct ivl_func<DERIVED, CONV>::call<R1, types::skip, types::skip, types::skip,
00560         types::skip, types::skip, types::skip, types::skip, types::skip,
00561         types::skip>
00562         :
00563         public ret<R1>
00564 {
00565         ret<R1>& r() { return static_cast<ret<R1>&>(*this); }
00566 
00567         template<class T1>
00568         call(T1& t1)
00569         {
00570                 //Note: old was: DERIVED()++(t1).output(r())
00571                 DERIVED()++(t1).tuple_output(internal::reftpl(r()));
00572         }
00573         template<class T1, class T2>
00574         call(T1& t1, T2& t2)
00575         {
00576                 DERIVED()++(t1, t2).tuple_output(internal::reftpl(r()));
00577         }
00578         template<class T1, class T2, class T3>
00579         call(T1& t1, T2& t2, T3& t3)
00580         {
00581                 DERIVED()++(t1, t2, t3).tuple_output(internal::reftpl(r()));
00582         }
00583 
00584 };
00585 
00586 } /* namespace ivl */
00587 
00588 #endif // IVL_CORE_DETAILS_IVL_FUNC_IVL_FUNC_HPP
00589 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations