https://svn.lrde.epita.fr/svn/oln/trunk/static
Index: ChangeLog
from Roland Levillain <roland(a)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
{
};
/// \}