
https://svn.lrde.epita.fr/svn/oln/trunk/static Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add a third kind of structure for virtual types to avoid endless recursions when their definitions involve the knowledge of the exact type of the class these virtual types belong to. * static/stc/vtypes.hh (single_vtype, single_vtype_): New template class. (internal::tag::single): New. (internal::tag::external): Rename as... (internal::tag::extended): ...this. (get_vtype_helper): Adjust and extended for internal::tag::single. (select_typedef): Extended retrieval algorithm. (type_of_): Likewise. Check the return type of the algorithm. More documentation. s/external/extended/. * static/tests/vtypes.cc: Conform to the new terminology. * static/tests/vtypes-multiple-supers.cc: Adjust. * tests/vtypes-and-exact.cc: Likewise. Aesthetic changes. (main): Exercize stc::is_any_. * static/stc/valist_aggregator.hh (valist_aggregator): Use virtual inheritance. stc/valist_aggregator.hh | 29 ++-- stc/vtypes.hh | 258 +++++++++++++++++++++++++++++++--------- tests/vtypes-and-exact.cc | 14 +- tests/vtypes-multiple-supers.cc | 2 tests/vtypes.cc | 2 5 files changed, 231 insertions(+), 74 deletions(-) Index: stc/vtypes.hh --- stc/vtypes.hh (revision 517) +++ stc/vtypes.hh (working copy) @@ -72,6 +72,8 @@ struct FIRST_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_TAG; struct THIRD_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_LIST; + struct NO_VALID_RETURN_TYPE_FOR_type_of_; + } // end of namespace stc::ERROR } // end of namespace stc @@ -223,6 +225,42 @@ /* Virtual types. */ \ /* --------------- */ \ \ + /** \brief Definition of virtual types. */ \ + /** */ \ + /** There a three kinds of structures for virtual types: */ \ + /** - internal vtypes (\a vtypes); */ \ + /** - single vtypes (\a single_vtype); */ \ + /** - extended vtypes (\a ext_vtype); */ \ + /** */ \ + /** A \a vtype structure can store one or several internal vtypes, */ \ + /** whereas a \a single_vtype or an \a ext_vtype structure can hold */ \ + /** one and only one vtype. */ \ + /** */ \ + /** See tests/tour.cc and tests/vtypes.cc for examples of use. */ \ + /** */ \ + /** A virtual type definition within a \a vtype structure cannot use */ \ + /** the form `stc_type_of(Exact, ...)', which would cause endless */ \ + /** recursions in the class hierarchy. Instead, such definitions */ \ + /** should be placed in \a single_vtype or \a ext_vtype structure. */ \ + /** */ \ + /** Definitions of single vtypes can be ``announced'' in the */ \ + /** corresponding internal vtypes structure, using the \a */ \ + /** mlc::undefined tag (i.e., a vtype defined as \a mlc::undefined in */ \ + /** \a vtypes can be re-defined in a \a single_vtype). */ \ + /** */ \ + /** Apart from this exception, a vtype shall be defined at most by */ \ + /** one of the three structures explained above. */ \ + /** */ \ + /** To put in a nushell, internal vtypes are the default way to define */ \ + /** the vtypes of a class (except those of the form */ \ + /** `stc_type_of(Exact, ...)'); single vtypes are used to transcend */ \ + /** this limitation; and extended vtypes are used to add new vtypes to */ \ + /** a class besides its initial vtypes. */ \ + \ + \ + /* Internal vtypes. */ \ + /* \{ */ \ + \ /** \brief Internal virtual types associated to \a from_type. */ \ /** */ \ /** Specialize this class for the desired \a from_type. */ \ @@ -252,7 +290,13 @@ { \ }; \ \ - /** \brief An external virtual type associated to \a from_type. */ \ + /* \} */ \ + \ + \ + /* Extended vtype. */ \ + /* \{ */ \ + \ + /** \brief An extended virtual type associated to \a from_type. */ \ /** */ \ /** Specialize this class for the desired \a from_type. */ \ template <typename category, typename from_type, typename typedef_type> \ @@ -260,7 +304,7 @@ { \ }; \ \ - /** \brief An external virtual type associated to \a from_type. */ \ + /** \brief An extended virtual type associated to \a from_type. */ \ /** Version for types without category. */ \ /** */ \ /** Specialize this class for the desired \a from_type. */ \ @@ -283,8 +327,52 @@ { \ }; \ \ + /* \} */ \ + \ + \ + /* Single vtype. */ \ + /* \{ */ \ + \ + /** \brief A single virtual type associated to \a from_type. */ \ + /** */ \ + /** Specialize this class for the desired \a from_type. */ \ + template <typename category, typename from_type, typename typedef_type> \ + struct single_vtype \ + { \ + }; \ + \ + /** \brief A single virtual type associated to \a from_type. */ \ + /** Version for types without category. */ \ + /** */ \ + /** Specialize this class for the desired \a from_type. */ \ + template <typename from_type, typename typedef_type> \ + struct single_vtype_ \ + { \ + }; \ + \ + /** Specialization of single_vtype for types without category. */ \ + template <typename from_type, typename typedef_type> \ + struct single_vtype<void, from_type, typedef_type> \ + : public single_vtype_<from_type, typedef_type> \ + { \ + }; \ + \ + /** End of the recursive construction of any single_vtype<> */ \ + /** hierarchy. */ \ + template <typename category, typename typedef_type> \ + struct single_vtype<category, mlc::none, typedef_type> \ + { \ + }; \ + \ + /* \} */ \ + \ + \ + /* -------------------------- */ \ + /* Packing of virtual types. */ \ + /* -------------------------- */ \ + \ /** Optional packing structure, to be specialized by the user. */ \ - /** See tests/vtypes.hh for an example of use. */ \ + /** See tests/vtypes.cc for an example of use. */ \ template <typename category, typename from_type> \ struct packed_vtypes \ { \ @@ -292,7 +380,6 @@ \ /** Optional packing structure, to be specialized by the user. */ \ /** Version for types without category. */ \ - /** See tests/vtypes.hh for an example of use. */ \ template <typename from_type> \ struct packed_vtypes_ \ { \ @@ -327,8 +414,10 @@ \ /** Tag for retrieval within internal vtypes. */ \ struct internal : public method {}; \ - /** Tag for retrieval within external vtypes. */ \ - struct external : public method {}; \ + /** Tag for retrieval within single vtypes. */ \ + struct single : public method {}; \ + /** Tag for retrieval within extended vtypes. */ \ + struct extended : public method {}; \ \ } /** end of stc::internal::tag */ \ \ @@ -356,15 +445,28 @@ }; \ \ /** Specialization of get_vtypes for retrievals within */ \ - /** external vtypes. */ \ + /** single vtypes. */ \ + template <typename category, \ + typename from_type, typename typedef_type> \ + struct get_vtype_helper<tag::single, category, \ + from_type, typedef_type> \ + { \ + /** Set of vtypes associated with FROM_TYPE. */ \ + typedef single_vtype<category, from_type, typedef_type> single_type; \ + /** Typedef in the current single_vtype (may be mlc::not_found). */ \ + typedef mlc_ret(single_type) ret; \ + }; \ + \ + /** Specialization of get_vtypes for retrievals within */ \ + /** extended vtypes. */ \ template <typename category, \ typename from_type, typename typedef_type> \ - struct get_vtype_helper<tag::external, category, \ + struct get_vtype_helper<tag::extended, category, \ from_type, typedef_type> \ { \ /** Set of vtypes associated with FROM_TYPE. */ \ typedef ext_vtype<category, from_type, typedef_type> ext_type; \ - /** Typedef in the current vtypes (may be mlc::not_found). */ \ + /** Typedef in the current ext_vtype (may be mlc::not_found). */ \ typedef mlc_ret(ext_type) ret; \ }; \ \ @@ -518,50 +620,78 @@ }; \ \ \ - /* ------------------------------------- */ \ - /* External/internal typedef selection. */ \ - /* ------------------------------------- */ \ + /* -------------------------------------------- */ \ + /* Internal/single/extended typedef selection. */ \ + /* -------------------------------------------- */ \ \ /** \brief Typedef selector. */ \ /** */ \ /** A virtual type is considered valid if and only if it has been */ \ - /** found as an internal vtype or (exclusive) as an external vtype. */ \ + /** found as an internal vtype or (exclusive) as an extended vtype. */ \ /** Other cases (no definition or a double definition) are invalid. */ \ /** */ \ /** \{ */ \ /** Fwd decl. */ \ - template <bool external_typedef_p, bool internal_typedef_p, \ - typename external_typedef, typename internal_typedef> \ + template \ + < typename internal_vtype_candidate, bool found_as_internal_vtype, \ + typename single_vtype_candidate, bool found_as_single_vtype, \ + typename extended_vtype_candidate, bool found_as_extended_vtype > \ struct select_typedef; \ \ - /** The typedef is found in both an external and an internal */ \ - /** type definitions: error. */ \ - template <typename external_typedef, typename internal_typedef> \ - struct select_typedef<true, true, external_typedef, internal_typedef> \ - { \ - /* No ret member. */ \ - }; \ - \ - /** The typedef is found neither in an external nor in an */ \ - /** internal type definition: error. */ \ - template <typename external_typedef, typename internal_typedef> \ - struct select_typedef<false, false, external_typedef, internal_typedef> \ - { \ - /* No ret member. */ \ - }; \ - \ - /** The typedef is found in an extternal definition only: good. */ \ - template <typename external_typedef, typename internal_typedef> \ - struct select_typedef<true, false, external_typedef, internal_typedef> \ + /** The typedef is defined as an internal vtype only: good. */ \ + template <typename internal_vtype_candidate, \ + typename single_vtype_candidate, \ + typename extended_vtype_candidate> \ + struct select_typedef<internal_vtype_candidate, true, \ + single_vtype_candidate, false, \ + extended_vtype_candidate, false> \ + { \ + typedef internal_vtype_candidate ret; \ + }; \ + \ + /** The typedef is defined as a single vtype only: good. */ \ + template <typename internal_vtype_candidate, \ + typename single_vtype_candidate, \ + typename extended_vtype_candidate> \ + struct select_typedef<internal_vtype_candidate, false, \ + single_vtype_candidate, true, \ + extended_vtype_candidate, false> \ + { \ + typedef single_vtype_candidate ret; \ + }; \ + \ + /** The typedef is defined as an extended vtype only: good. */ \ + template <typename internal_vtype_candidate, \ + typename single_vtype_candidate, \ + typename extended_vtype_candidate> \ + struct select_typedef<internal_vtype_candidate, false, \ + single_vtype_candidate, false, \ + extended_vtype_candidate, true> \ + { \ + typedef extended_vtype_candidate ret; \ + }; \ + \ + /** Special case. The typedef is <b>declared</b> as mlc::undefined */ \ + /** in internal vtypes, and <b>defined</b> as a single vtype: good. */ \ + template <typename single_vtype_candidate, \ + typename extended_vtype_candidate> \ + struct select_typedef<mlc::undefined, true, \ + single_vtype_candidate, true, \ + extended_vtype_candidate, false> \ + { \ + typedef single_vtype_candidate ret; \ + }; \ + \ + /** Other cases: error (the typedef is not defined or defined more */ \ + /** than once, hence \a mlc::not_found is returned). */ \ + template \ + < typename internal_vtype_candidate, bool found_as_internal_vtype, \ + typename single_vtype_candidate, bool found_as_single_vtype, \ + typename extended_vtype_candidate, bool found_as_extended_vtype > \ + struct select_typedef \ { \ - typedef external_typedef ret; \ - }; \ - \ - /** The typedef is found in an internal definition only: good. */ \ - template <typename external_typedef, typename internal_typedef> \ - struct select_typedef<false, true, external_typedef, internal_typedef> \ - { \ - typedef internal_typedef ret; \ + /* Error, not valid typedef found. */ \ + typedef mlc::not_found ret; \ }; \ /** \} */ \ \ @@ -575,29 +705,47 @@ /* Get the exact type of \a from_type. */ \ typedef stc_to_exact(from_type) from_exact_type; \ \ - /* Look for the typedef in internal types. */ \ + /* Look for the typedef in internal vtypes. */ \ typedef typename \ internal::rec_get_vtype<internal::tag::internal, category, \ from_exact_type, typedef_type>::ret \ - internal_typedef; \ - /* Look for the typedef as an external type. */ \ + internal_vtype_candidate; \ + /* Look for the typedef as a single vtype definition. */ \ typedef typename \ - internal::rec_get_vtype<internal::tag::external, category, \ + internal::rec_get_vtype<internal::tag::single, category, \ from_exact_type, typedef_type>::ret \ - external_typedef; \ + single_vtype_candidate; \ + /* Look for the typedef as an extended vtype. */ \ + typedef typename \ + internal::rec_get_vtype<internal::tag::extended, category, \ + from_exact_type, typedef_type>::ret \ + extended_vtype_candidate; \ \ - /* Did we found the virtual type? */ \ - static const bool found_internal_p = \ - mlc_bool(mlc::is_found_<internal_typedef>); \ - static const bool found_external_p = \ - mlc_bool(mlc::is_found_<external_typedef>); \ + /* Did we found the virtual type in any of the vtypes structures? */ \ + static const bool found_as_internal_vtype = \ + mlc_bool(mlc::is_found_<internal_vtype_candidate>); \ + static const bool found_as_single_vtype = \ + mlc_bool(mlc::is_found_<single_vtype_candidate>); \ + static const bool found_as_extended_vtype = \ + mlc_bool(mlc::is_found_<extended_vtype_candidate>); \ + \ + /* Find an eligible typedef. */ \ + typedef typename \ + internal::select_typedef< \ + internal_vtype_candidate, found_as_internal_vtype, \ + single_vtype_candidate, found_as_single_vtype, \ + extended_vtype_candidate, found_as_extended_vtype \ + >::ret candidate; \ \ typedef typename \ - internal::select_typedef<found_external_p, found_internal_p, \ - external_typedef, internal_typedef>::ret ret; \ + mlc::assert_and_return_< \ + mlc_neq(candidate, mlc::not_found), \ + candidate, \ + stc::ERROR::NO_VALID_RETURN_TYPE_FOR_type_of_ \ + >::ret ret; \ }; \ \ - struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + struct e_n_d__w_i_t_h___s_e_m_i_c_o_l_o_n /*---------------------. Index: tests/vtypes.cc --- tests/vtypes.cc (revision 517) +++ tests/vtypes.cc (working copy) @@ -148,7 +148,7 @@ typedef long quux_type; }; - /// An external type associated to my::B. + /// An extended type associated to my::B. template <> struct ext_vtype<category::my_cat, B, typedef_::yin_type> { Index: tests/vtypes-multiple-supers.cc --- tests/vtypes-multiple-supers.cc (revision 517) +++ tests/vtypes-multiple-supers.cc (working copy) @@ -33,7 +33,7 @@ // This test focuses on the support of virtual types in hierachies // with multiple inheritance. -// FIXME: To do: Check external vtypes, too. +// FIXME: To do: Check extended vtypes, too. /// Helper macros. /// \{ Index: tests/vtypes-and-exact.cc --- tests/vtypes-and-exact.cc (revision 517) +++ tests/vtypes-and-exact.cc (working copy) @@ -100,13 +100,12 @@ /// Types associated to my::A. template <typename Exact> - struct vtypes< category::my_cat, my::A<Exact> > + struct vtypes< category::my_cat, A<Exact> > { // A native type. typedef int foo_type; - // A Metalic value, used here is to ensure that - // mlc::abstract::values are accepted as virtual types, as well as - // any other type). + // A Metalic value, used here to ensure that mlc::abstract::values + // are accepted as virtual types, as well as any other type). typedef mlc::int_<42> bar_type; // An undefined type. typedef mlc::undefined baz_type; @@ -157,7 +156,7 @@ typedef long quux_type; }; - /// An external type associated to my::B. + /// An extended type associated to my::B. template <typename Exact> struct ext_vtype<category::my_cat, B<Exact>, typedef_::yin_type> { @@ -228,6 +227,11 @@ mlc::assert_<mlc_is_a_(C, A)>::check(); mlc::assert_<mlc_is_a_(C, B)>::check(); + // Ensure stc::is_any_ works properly. + mlc::assert_< stc::is_any_< A<C> > >::check(); + mlc::assert_< stc::is_any_< B<C> > >::check(); + mlc::assert_< stc::is_any_< C > >::check(); + // Check exact types of A<C> and B<C>. mlc::assert_<mlc_eq(stc_to_exact_(A<C>), C)>::check(); mlc::assert_<mlc_eq(stc_to_exact_(B<C>), C)>::check(); Index: stc/valist_aggregator.hh --- stc/valist_aggregator.hh (revision 517) +++ stc/valist_aggregator.hh (working copy) @@ -71,28 +71,30 @@ /// Version for 2 super classes. template <typename E1, typename E2> struct valist_aggregator< mlc::valist_ <E1,E2> > : - public E1, public E2 + virtual public E1, virtual public E2 { }; /// Version for 3 super classes. template <typename E1, typename E2, typename E3> struct valist_aggregator< mlc::valist_ <E1,E2,E3 > > : - public E1, public E2, public E3 + virtual public E1, virtual public E2, virtual public E3 { }; /// Version for 4 super classes. template <typename E1, typename E2, typename E3, typename E4> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4> > : - public E1, public E2, public E3, public E4 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4 { }; /// Version for 5 super classes. template <typename E1, typename E2, typename E3, typename E4, typename E5> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4,E5> > : - public E1, public E2, public E3, public E4, public E5 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4, virtual public E5 { }; @@ -100,8 +102,8 @@ template <typename E1, typename E2, typename E3, typename E4, typename E5, typename E6> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4,E5,E6> > : - public E1, public E2, public E3, public E4, public E5, - public E6 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4, virtual public E5, virtual public E6 { }; @@ -109,8 +111,9 @@ template <typename E1, typename E2, typename E3, typename E4, typename E5, typename E6, typename E7> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4,E5,E6,E7> > : - public E1, public E2, public E3, public E4, public E5, - public E6, public E7 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4, virtual public E5, virtual public E6, + virtual public E7 { }; @@ -118,8 +121,9 @@ template <typename E1, typename E2, typename E3, typename E4, typename E5, typename E6, typename E7, typename E8> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4,E5,E6,E7,E8> > : - public E1, public E2, public E3, public E4, public E5, - public E6, public E7, public E8 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4, virtual public E5, virtual public E6, + virtual public E7, virtual public E8 { }; @@ -127,8 +131,9 @@ template <typename E1, typename E2, typename E3, typename E4, typename E5, typename E6, typename E7, typename E8, typename E9> struct valist_aggregator< mlc::valist_ <E1,E2,E3,E4,E5,E6,E7,E8,E9> > : - public E1, public E2, public E3, public E4, public E5, - public E6, public E7, public E8, public E9 + virtual public E1, virtual public E2, virtual public E3, + virtual public E4, virtual public E5, virtual public E6, + virtual public E7, virtual public E8, virtual public E9 { }; /// \}