722: Polish stc/scoop2.hh.

https://svn.lrde.epita.fr/svn/oln/trunk/static Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Polish stc/scoop2.hh. The work is far from beeing finished; we still have to address the problem of deferred virtual types. * doc/algorithms.ml: Add a new (non working) example. Typos. * stc/scoop.hh (stc_find_deduce_vtype): Add a missing argument. * stc/scoop2.hh (stc::none): New. (stc::is_found_, stc::is_not_found_): New. (SCOOPED_NAMESPACE): Set to oln. (stc_match_pair_0p_with, stc_match_pair_1p_with (stc_match_pair_2p_with, stc_match_pair_1p_with_error) (stc_match_pair_2p_with_error): New macros. (merge2_): Use them to simplify this struct. (stc_match_triple_0p_with, stc_match_triple_1p_with) (stc_match_triple_2p_with, stc_match_triple_3p_with) (stc_match_triple_2p_with_error, stc_match_triple_3p_with_error): New macros. (merge3_): Use them to simplify this struct. (find): Rename struct as... (find_vtype): ...this. (vtype): New struct. (stc_deferred_vtype, stc_vtype_, stc_vtype) (stc_find_deduce_vtype_, stc_find_deduce_vtype) (stc_deduce_deferred_vtype, stc_deduce_vtype_, stc_deduce_vtype): New macros. doc/algorithms.ml | 41 +++ stc/scoop.hh | 2 stc/scoop2.hh | 582 +++++++++++++++++++++++++++++++----------------------- 3 files changed, 378 insertions(+), 247 deletions(-) Index: doc/algorithms.ml --- doc/algorithms.ml (revision 721) +++ doc/algorithms.ml (working copy) @@ -80,8 +80,8 @@ | Stc_Not_found, u -> u (* local_res == stc::abstract. *) - | Stc_Abstract, Stc_Abstract -> Stc_Abstract | Stc_Abstract, Stc_Not_found -> Stc_Abstract + | Stc_Abstract, Stc_Abstract -> Stc_Abstract | Stc_Abstract, Stc_Final _ -> error "Final VT redefined abstract" | Stc_Abstract, _ -> error "VT redefined abstract." @@ -182,7 +182,7 @@ end | _ -> error "find_rec: source is not a SCOOP class." -(* Like find_rec, but only search in the inheritance branch. *) +(* Like find_rec, but search only in the inheritance branch. *) and find_rec_in_supers (source : cxx_type) (target : string) : cxx_type = match source with | Stc_None -> Stc_Not_found @@ -206,7 +206,6 @@ ;; - (*-----------. | Examples. | `-----------*) @@ -611,3 +610,39 @@ assert (find image2d_int "value_type" = Std_Int); assert (find value_cast__image2d_int__float "value_type" = Std_Float);; + + +(*--------------. +| Limitations. | +`--------------*) + +(* Another Olena-like example with recursive definitions. + + class internal_dpoint_nd < stc::none + { + vtype mydim_type = find dpoint2d "dim_type"; + } + + class dpoint2d < internal_dpoint_nd + { + // Dummy value (because our C++ types are limited in this prototype). + vtype dim_type = int + } +*) +(* However, we can't write this + + let rec internal_dpoint_nd = + Scoop_Class { super = Stc_None; + vtypes = create_vtypes ["mydim_type", + (find dpoint2d "dim_type")] } + and dpoint2d = + Scoop_Class { super = internal_dpoint_nd; + vtypes = create_vtypes ["dim_type", Std_Int] } + in + find dpoint2d "dim_type";; + + because of the limitations of the recursive definitions of OCaml. + These limitations reflect issues w.r.t. recursive definitions in + C++ too. A new mechanism is needed, both in this OCaml prototype + and in its C++ counterpart (stc/scoop2.hh). +*) Index: stc/scoop.hh --- stc/scoop.hh (revision 721) +++ stc/scoop.hh (working copy) @@ -801,7 +801,7 @@ Namespace::typedef_::Target1##_type>::ret, \ Namespace::typedef_::Target2##_type>::ret -# define stc_find_deduce_vtype(Namespace, From, Target) \ +# define stc_find_deduce_vtype(Namespace, From, Target1, Target2) \ typename \ Namespace::find_vtype< typename \ Namespace::find_vtype<From, \ Index: stc/scoop2.hh --- stc/scoop2.hh (revision 721) +++ stc/scoop2.hh (working copy) @@ -39,14 +39,38 @@ namespace stc { - + /* FIXME: Define a real stc::none, instead of making it an alias of + mlc::none. For compatibility purpose with the current + implementation of the SCOOP 2 paradigme (see stc/scoop.hh), we + need to have stc::none be equal to mlc::none. */ +#if 0 struct none {}; +#endif + using mlc::none; + struct not_found; struct abstract; struct not_delegated; struct not_delegated_abstract; template <typename T> struct final; + + /// \brief Shortcuts for comparison with stc::not_found. + /// + /// Duplicate with their Metalic's homonyms, but still useful, since + /// they deal with std::not_found (not mlc::not_found). + /// \{ + template <typename T> + struct is_not_found_ : public mlc_is_a(T, stc::not_found)::bexpr + { + }; + + template <typename T> + struct is_found_ : public mlc_is_not_a(T, stc::not_found)::bexpr + { + }; + /// \} + namespace ERROR { struct IN_find__VIRTUAL_TYPE_IS_ABSTRACT; @@ -73,8 +97,10 @@ // Based on doc/algorithm.ml. -// FIXME: Hack. -#define SCOOPED_NAMESPACE my +// FIXME: Temp. hack. The contents of SCOOPED_NAMESPACE will be +// available later as a macro, as in stc/scoop.hh. Currently, it's +// easier to work without this macro equipment. +#define SCOOPED_NAMESPACE oln // ------------------------------------------------------------ find_local. @@ -152,106 +178,124 @@ // -------------------------------------------------------------- merge2. +// Shortcuts macros. +#define stc_match_pair_0p_with(Local, Super, Res) \ + template <> \ + struct match_with< Local, Super > \ + { \ + typedef Res ret; \ + } + +#define stc_match_pair_1p_with(T1, Local, Super, Res) \ + template < typename T1 > \ + struct match_with< Local, Super > \ + { \ + typedef Res ret; \ + } + +#define stc_match_pair_2p_with(T1, T2, Local, Super, Res) \ + template < typename T1, typename T2 > \ + struct match_with< Local, Super > \ + { \ + typedef Res ret; \ + } + +// Erroneous cases. +#define stc_match_pair_1p_with_error(T1, Local, Super, Msg) \ + template < typename T1 > \ + struct match_with< Local, Super > : \ + mlc::abort_< T1, Msg > \ + { \ + } + +#define stc_match_pair_2p_with_error(T1, T2, Local, Super, Msg) \ + template < typename T1, typename T2 > \ + struct match_with< Local, Super > : \ + mlc::abort_< T2, Msg > \ + { \ + } + + namespace merge2_ { // Forward declaration. template <typename T, typename U> struct match_with; - // super_res == stc::not_found. - template <> - struct match_with<stc::abstract, stc::not_found> - { - typedef stc::abstract ret; - }; - template <> - struct match_with<stc::not_found, stc::not_found> - { - typedef stc::not_found ret; - }; - template <typename T> - struct match_with<stc::final<T>, stc::not_found> - { - typedef stc::final<T> ret; - }; + /*------------------------------. + | local_res == stc::not_found. | + `------------------------------*/ - template <typename T> - struct match_with<T, stc::not_found> - { - typedef T ret; - }; + stc_match_pair_0p_with(stc::not_found, stc::not_found, + stc::not_found); + stc_match_pair_0p_with(stc::not_found, stc::abstract, + stc::not_found); - // super_res == stc::abstract. - template <> - struct match_with<stc::not_found, stc::abstract> - { - typedef stc::not_found ret; - }; + stc_match_pair_1p_with(U, + stc::not_found, stc::final<U>, + stc::final<U>); - template <> - struct match_with<stc::abstract, stc::abstract> - { - typedef stc::abstract ret; - }; + stc_match_pair_1p_with(U, + stc::not_found, U, + U); - template <typename T> - struct match_with<stc::final<T>, stc::abstract> - { - typedef stc::final<T> ret; - }; - template <typename T> - struct match_with<T, stc::abstract> - { - typedef T ret; - }; + /*-----------------------------. + | local_res == stc::abstract. | + `-----------------------------*/ + stc_match_pair_0p_with(stc::abstract, stc::not_found, + stc::abstract); - // super_res == stc::final<U>. - template <typename U> - struct match_with<stc::abstract, stc::final<U> > : - mlc::abort_<U, stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED_ABSTRACT> - { - }; + stc_match_pair_0p_with(stc::abstract, stc::abstract, + stc::abstract); - template <typename U> - struct match_with<stc::not_found, stc::final<U> > - { - typedef stc::final<U> ret; - }; + stc_match_pair_1p_with_error(U, + stc::abstract, stc::final<U>, + stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED_ABSTRACT); - template <typename T, typename U> - struct match_with<stc::final<T>, stc::final<U> > : - mlc::abort_<U, stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED_FINAL> - { - }; + stc_match_pair_1p_with_error(U, + stc::abstract, U, + stc::ERROR::IN_merge2__VIRTUAL_TYPE_REDEFINED_ABSTRACT); - template <typename T, typename U> - struct match_with<T, stc::final<U> > : - mlc::abort_<U, stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED> - { - }; + /*-----------------------------. + | local_res == stc::final<T>. | + `-----------------------------*/ - // super_res == U. - template <typename U> - struct match_with<stc::abstract, U> : - mlc::abort_<U, stc::ERROR::IN_merge2__VIRTUAL_TYPE_REDEFINED_ABSTRACT> - { - }; + stc_match_pair_1p_with(T, + stc::final<T>, stc::not_found, + stc::final<T>); - template <typename U> - struct match_with<stc::not_found, U> - { - typedef U ret; - }; + stc_match_pair_1p_with(T, + stc::final<T>, stc::abstract, + stc::final<T>); - template <typename T, typename U> - struct match_with<stc::final<T>, U> - { - typedef stc::final<T> ret; - }; + stc_match_pair_2p_with_error(T, U, + stc::final<T>, stc::final<U>, + stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED_FINAL); + + stc_match_pair_2p_with(T, U, + stc::final<T>, U, + stc::final<T>); + + + /*-----------------. + | local_res == T. | + `-----------------*/ + + stc_match_pair_1p_with(T, + T, stc::not_found, + T); + + stc_match_pair_1p_with(T, + T, stc::abstract, + T); + + stc_match_pair_2p_with_error(T, U, + T, stc::final<U>, + stc::ERROR::IN_merge2__FINAL_VIRTUAL_TYPE_REDEFINED); template <typename T, typename U> struct match_with @@ -261,6 +305,12 @@ } // end of namespace merge2_ +#undef stc_match_pair_2p_with_error +#undef stc_match_pair_1p_with_error +#undef stc_match_pair_2p_with +#undef stc_match_pair_1p_with +#undef stc_match_pair_0p_with + template <typename local_res, typename super_res> struct merge2 { @@ -271,38 +321,50 @@ // -------------------------------------------------------------- merge3. - // FIXME: Undef these macros after the definition of merge3. - -#define stc_match_0p_with(Local, Super, Deleg, Res) \ +// Shortcuts macros. +#define stc_match_triple_0p_with(Local, Super, Deleg, Res) \ template <> \ struct match_with< Local, Super, Deleg > \ { \ typedef Res ret; \ } -#define stc_match_1p_with(T1, Local, Super, Deleg, Res) \ +#define stc_match_triple_1p_with(T1, Local, Super, Deleg, Res) \ template <typename T1> \ struct match_with< Local, Super, Deleg > \ { \ typedef Res ret; \ } -#define stc_match_2p_with(T1, T2, Local, Super, Deleg, Res) \ +#define stc_match_triple_2p_with(T1, T2, Local, Super, Deleg, Res) \ template <typename T1, typename T2> \ struct match_with< Local, Super, Deleg > \ { \ typedef Res ret; \ } -#define stc_match_3p_with(T1, T2, T3, Local, Super, Deleg, Res) \ +#define stc_match_triple_3p_with(T1, T2, T3, Local, Super, Deleg, Res) \ template <typename T1, typename T2, typename T3> \ struct match_with< Local, Super, Deleg > \ { \ typedef Res ret; \ } - // FIXME: Example of use. - // stc_match_with(stc::not_found, stc::not_found, stc::not_found, stc::not_found); +// Erroneous cases. +#define stc_match_triple_2p_with_error(T1, T2, Local, Super, Deleg, Msg) \ + template < typename T1, typename T2 > \ + struct match_with< Local, Super, Deleg > : \ + mlc::abort_< T2, Msg > \ + { \ + } + +#define stc_match_triple_3p_with_error(T1, T2, T3, Local, Super, Deleg, Msg) \ + template < typename T1, typename T2, typename T3 > \ + struct match_with< Local, Super, Deleg > : \ + mlc::abort_< T3, Msg > \ + { \ + } + namespace merge3_ { @@ -310,198 +372,155 @@ template <typename T, typename U, typename V> struct match_with; - // local_res == stc::not_found. - template <> - struct match_with<stc::not_found, stc::not_found, stc::not_found> - { - typedef stc::not_found ret; - }; + /*------------------------------. + | local_res == stc::not_found. | + `------------------------------*/ - template <> - struct match_with<stc::not_found, stc::not_found, stc::abstract> - { - typedef stc::not_found ret; - }; + // super_res == stc::not_found. + stc_match_triple_0p_with(stc::not_found, stc::not_found, stc::not_found, + stc::not_found); - template <typename V> - struct match_with<stc::not_found, stc::not_found, stc::final<V> > - { - typedef stc::final<V> ret; - }; + stc_match_triple_0p_with(stc::not_found, stc::not_found, stc::abstract, + stc::not_found); - template <typename V> - struct match_with<stc::not_found, stc::not_found, V> - { - typedef V ret; - }; + stc_match_triple_1p_with(V, + stc::not_found, stc::not_found, stc::final<V>, + stc::final<V>); + + stc_match_triple_1p_with(V, + stc::not_found, stc::not_found, V, + V); + // super_res == stc::abstract. + stc_match_triple_0p_with(stc::not_found, stc::abstract, stc::not_found, + stc::not_found); - template <> - struct match_with<stc::not_found, stc::abstract, stc::not_found> - { - typedef stc::not_found ret; - }; + stc_match_triple_0p_with(stc::not_found, stc::abstract, stc::abstract, + stc::abstract); - template <> - struct match_with<stc::not_found, stc::abstract, stc::abstract> - { - typedef stc::abstract ret; - }; + stc_match_triple_1p_with(V, + stc::not_found, stc::abstract, stc::final<V>, + stc::final<V>); - template <typename V> - struct match_with<stc::not_found, stc::abstract, stc::final<V> > - { - typedef stc::final<V> ret; - }; + stc_match_triple_1p_with(V, + stc::not_found, stc::abstract, V, + V); - template <typename V> - struct match_with<stc::not_found, stc::abstract, V> - { - typedef V ret; - }; + // super_res is a concrete type. + stc_match_triple_2p_with(U, V, + stc::not_found, stc::final<U>, V, + stc::final<U>); + stc_match_triple_2p_with(U, V, + stc::not_found, U, V, + U); - template <typename U, typename V> - struct match_with<stc::not_found, stc::final<U>, V> - { - typedef stc::final<U> ret; - }; - template <typename U, typename V> - struct match_with<stc::not_found, U, V> - { - typedef U ret; - }; + /*-----------------------------. + | local_res == stc::abstract. | + `-----------------------------*/ + // super_res == stc::not_found. + stc_match_triple_0p_with(stc::abstract, stc::not_found, stc::not_found, + stc::abstract); - // local_res == stc::abstract. - template <> - struct match_with<stc::abstract, stc::not_found, stc::not_found> - { - typedef stc::abstract ret; - }; + stc_match_triple_0p_with(stc::abstract, stc::not_found, stc::abstract, + stc::abstract); - template <> - struct match_with<stc::abstract, stc::not_found, stc::abstract> - { - typedef stc::abstract ret; - }; + stc_match_triple_1p_with(V, + stc::abstract, stc::not_found, stc::final<V>, + stc::final<V>); + + stc_match_triple_1p_with(V, + stc::abstract, stc::not_found, V, + V); - template <typename V> - struct match_with<stc::abstract, stc::not_found, stc::final<V> > - { - typedef stc::final<V> ret; - }; - template <typename V> - struct match_with<stc::abstract, stc::not_found, V > - { - typedef V ret; - }; + // super_res == stc::abstract. + stc_match_triple_0p_with(stc::abstract, stc::abstract, stc::not_found, + stc::abstract); + stc_match_triple_0p_with(stc::abstract, stc::abstract, stc::abstract, + stc::abstract); - template <> - struct match_with<stc::abstract, stc::abstract, stc::not_found> - { - typedef stc::abstract ret; - }; + stc_match_triple_1p_with(V, + stc::abstract, stc::abstract, stc::final<V>, + stc::final<V>); - template <> - struct match_with<stc::abstract, stc::abstract, stc::abstract> - { - typedef stc::abstract ret; - }; + stc_match_triple_1p_with(V, + stc::abstract, stc::abstract, V, + V); - template <typename V> - struct match_with<stc::abstract, stc::abstract, stc::final<V> > - { - typedef stc::final<V> ret; - }; - template <typename V> - struct match_with<stc::abstract, stc::abstract, V> - { - typedef V ret; - }; + // super_res == stc::not_delegated_abstract. + stc_match_triple_1p_with(V, + stc::abstract, stc::not_delegated_abstract, V, + stc::not_delegated_abstract); + stc_match_triple_1p_with(V, + stc::abstract, stc::not_delegated, V, + stc::not_delegated_abstract); - template <typename V> - struct match_with<stc::abstract, stc::not_delegated_abstract, V> - { - typedef stc::not_delegated_abstract ret; - }; - template <typename V> - struct match_with<stc::abstract, stc::not_delegated, V> - { - typedef stc::not_delegated_abstract ret; - }; + // super_res is a concrete type. + stc_match_triple_2p_with_error(U, V, + stc::abstract, stc::final<U>, V, + stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED_ABSTRACT); + stc_match_triple_2p_with_error(U, V, + stc::abstract, U, V, + stc::ERROR::IN_merge3__VIRTUAL_TYPE_REDEFINED_ABSTRACT); - template <typename U, typename V> - struct match_with<stc::abstract, stc::final<U>, V> : - mlc::abort_<V, stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED_ABSTRACT> - { - }; - template <typename U, typename V> - struct match_with<stc::abstract, U, V> : - mlc::abort_<V, stc::ERROR::IN_merge3__VIRTUAL_TYPE_REDEFINED_ABSTRACT> - { - }; + /*----------------------------------. + | local_res == stc::not_delegated. | + `----------------------------------*/ + stc_match_triple_1p_with(V, + stc::not_delegated, stc::not_found, V, + stc::not_delegated); - // local_res == stc::not_delegated. - template <typename V> - struct match_with<stc::not_delegated, stc::not_found, V> - { - typedef stc::not_delegated ret; - }; + stc_match_triple_1p_with(V, + stc::not_delegated, stc::abstract, V, + stc::not_delegated_abstract); - template <typename V> - struct match_with<stc::not_delegated, stc::abstract, V> - { - typedef stc::not_delegated_abstract ret; - }; + stc_match_triple_1p_with(V, + stc::not_delegated, stc::not_delegated_abstract, V, + stc::not_delegated_abstract); - template <typename V> - struct match_with<stc::not_delegated, stc::not_delegated_abstract, V> - { - typedef stc::not_delegated_abstract ret; - }; + /*----------------------------------------------. + | local_res == stc::not_delegated_abstract. *) | + `----------------------------------------------*/ - // local_res == stc::not_delegated_abstract. *) /* FIXME: Shouldn't we introduce a means to tag a vtype both as abstract *and* not delegated? (Currently, the rule below prevents this). */ - template <typename U, typename V> - struct match_with<stc::not_delegated_abstract, U, V> : - mlc::abort_<V, stc::ERROR::IN_merge3__LOCAL_DECLARATION_OF_NOT_DELEGATED_AND_ABSTRACT> - { - }; + stc_match_triple_2p_with_error(U, V, + stc::not_delegated_abstract, U, V, + stc::ERROR::IN_merge3__LOCAL_DECLARATION_OF_NOT_DELEGATED_AND_ABSTRACT); - // local_res == stc::final<T>. - template <typename T, typename U, typename V> - struct match_with<stc::final<T>, stc::final<U>, V> : - mlc::abort_<V, stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED_FINAL> - { - }; + /*-----------------------------. + | local_res == stc::final<T>. | + `-----------------------------*/ - template <typename T, typename U, typename V> - struct match_with<stc::final<T>, U, V> - { - typedef stc::final<T> ret; - }; + stc_match_triple_3p_with_error(T, U, V, + stc::final<T>, stc::final<U>, V, + stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED_FINAL); + stc_match_triple_3p_with(T, U, V, + stc::final<T>, U, V, + stc::final<T>); - // local_res == T. - template <typename T, typename U, typename V> - struct match_with<T, stc::final<U>, V> : - mlc::abort_<V, stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED> - { - }; + + /*-----------------. + | local_res == T. | + `-----------------*/ + + stc_match_triple_3p_with_error(T, U, V, + T, stc::final<U>, V, + stc::ERROR::IN_merge3__FINAL_VIRTUAL_TYPE_REDEFINED); template <typename T, typename U, typename V> struct match_with @@ -511,6 +530,15 @@ } // end of namespace merge3_ + +#undef stc_match_triple_3p_with_error +#undef stc_match_triple_2p_with_error +#undef stc_match_triple_3p_with +#undef stc_match_triple_2p_with +#undef stc_match_triple_1p_with +#undef stc_match_triple_0p_with + + template <typename local_res, typename super_res, typename delegatee_res> struct merge3 { @@ -669,21 +697,89 @@ } // end of namespace find_ + + /// Find a virtual type. template <typename source, typename target> - struct find + struct find_vtype { typedef typename find_rec<source, target>::ret res; // Result. typedef typename find_::match_with<res>::ret ret; }; + + /// Find a virtual type, and ensure it is found. + template <typename from, typename target> + struct vtype + { + typedef typename find_vtype<from, target>::ret res; + struct check_ : mlc::assert_< mlc::is_found_<res> > + { + typedef res ret; + }; + typedef typename check_::ret ret; + }; + } /* end of SCOOPED_NAMESPACE */ +// FIXME: Document all these macros. + # define stc_find_vtype_(Namespace, Source, Target) \ - Namespace::find<Source, Namespace::typedef_::Target##_type>::ret + Namespace::find_vtype<Source, Namespace::typedef_::Target##_type>::ret # define stc_find_vtype(Namespace, Source, Target) \ typename stc_find_vtype_(Namespace, Source, Target) +// Dummy alias, for compatibility purpose (deferred virtual types are +// not currently handled by this version of stc/scoop2.hh). +# define stc_deferred_vtype(Namespace, From, Target) \ + stc_find_vtype(Namespace, From, Target) + +# define stc_vtype_(Namespace, From, Target) \ + Namespace::vtype<From, Namespace::typedef_::Target##_type>::ret + +# define stc_vtype(Namespace, From, Target) \ + typename stc_vtype_(Namespace, From, Target) + +# define stc_find_deduce_vtype_(Namespace, From, Target1, Target2) \ + Namespace::find_vtype< \ + Namespace::find_vtype< \ + From, \ + Namespace::typedef_::Target1##_type \ + >::ret, \ + Namespace::typedef_::Target2##_type \ + >::ret + +# define stc_find_deduce_vtype(Namespace, From, Target1, Target2) \ + typename Namespace::find_vtype< \ + typename Namespace::find_vtype< \ + From, \ + Namespace::typedef_::Target1##_type \ + >::ret, \ + Namespace::typedef_::Target2##_type \ + >::ret + +# define stc_deduce_deferred_vtype(Namespace, From, Target1, Target2) \ + stc_find_deduce_vtype(Namespace, From, Target1, Target2) + +# define stc_deduce_vtype_(Namespace, From, Target1, Target2) \ + Namespace::vtype< \ + Namespace::vtype< \ + From, \ + Namespace::typedef_::Target1##_type \ + >::ret, \ + Namespace::typedef_::Target2##_type \ + >::ret + +# define stc_deduce_vtype(Namespace, From, Target1, Target2) \ + typename Namespace::vtype< \ + typename Namespace::vtype< \ + From, \ + Namespace::typedef_::Target1##_type \ + >::ret, \ + Namespace::typedef_::Target2##_type \ + >::ret + + #endif // ! STC_SCOOP2_HH
participants (1)
-
Roland Levillain