
https://svn.lrde.epita.fr/svn/oln/trunk/static Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Perform virtual type retrieval using the exact type of a class. * stc/vtypes.hh (type_of_): Get the exact type of the ``from_type'' class, and perform the retrieval on it (instead of from_type directly). * tests/vtypes-and-exact.cc: New test. * tests/Makefile.am (check_PROGRAMS): Add vtypes-and-exact.cc. (vtypes_and_exact_SOURCES): New. stc/vtypes.hh | 11 +- tests/Makefile.am | 2 tests/vtypes-and-exact.cc | 250 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+), 4 deletions(-) Index: tests/vtypes-and-exact.cc --- tests/vtypes-and-exact.cc (revision 0) +++ tests/vtypes-and-exact.cc (revision 0) @@ -0,0 +1,250 @@ +// Copyright (C) 2006 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#include <stc/any.hh> +#include <stc/vtypes.hh> +#include <mlc/cmp.hh> +#include <mlc/assert.hh> +#include <mlc/int.hh> + +// Check the virtual types system on a SCOOP hierarchy propagating the +// exact (static) type throughout the inheritance tree (using +// stc::any). + +// Helper macros. +#define my_type_of(FromType, Typedef) \ + typename my_type_of_(FromType, Typedef) + +#define my_type_of_(FromType, Typedef) \ + stc_local_type_of_(my::category::my_cat, FromType, Typedef) + +namespace my +{ + /*-----------. + | Typedefs. | + `-----------*/ + + mlc_decl_typedef(foo_type); + mlc_decl_typedef(bar_type); + mlc_decl_typedef(baz_type); + mlc_decl_typedef(quux_type); + mlc_decl_typedef(yin_type); + mlc_decl_typedef(zorg_type); + + + /*----------------------. + | Namespace equipment. | + `----------------------*/ + + stc_equip_namespace_with_vtypes(); + + + /*-----------. + | Category. | + `-----------*/ + + // We only use one category here. + namespace category + { + struct my_cat; + } + + /// Packing of virtual types of any class belonging to the category my::cat. + template <typename T> + struct packed_vtypes <category::my_cat, T> + { + typedef my_type_of(T, foo) foo_type; + typedef my_type_of(T, bar) bar_type; + typedef my_type_of(T, baz) baz_type; + + static void ensure() + { + mlc::assert_< mlc_is_ok(foo_type) >::check(); + mlc::assert_< mlc_is_ok(bar_type) >::check(); + mlc::assert_< mlc_is_ok(baz_type) >::check(); + } + }; + + + /*----------------------------------------. + | A<Exact> --|> stc::any__simple<Exact>. | + `----------------------------------------*/ + + // Forward declaration. + template <typename Exact> + struct A; + + /// Types associated to my::A. + template <typename Exact> + struct vtypes< category::my_cat, my::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). + typedef mlc::int_<42> bar_type; + // An undefined type. + typedef mlc::undefined baz_type; + }; + + template <typename Exact> + struct A : public stc::any__simple<Exact> + { + // Aliases. + typedef my_type_of(A, foo) foo_type; + typedef my_type_of(A, bar) bar_type; + typedef my_type_of(A, baz) baz_type; + + ~A() + { + // packed_vtypes< category::my, A<Exact> > is not checked here, + // since A's baz_type virtual type is undefined. + } + }; + + + /*--------------------------. + | B<Exact> ---|> A<Exact>. | + `--------------------------*/ + + // Forward declaration. + template <typename Exact> + struct B; + + // Super type. + template <typename Exact> + struct set_super_type< B<Exact> > + { + typedef A<Exact> ret; + }; + + /// Types associated to my::B. + template <typename Exact> + struct vtypes< category::my_cat, B<Exact> > + { + // (foo is left untouched.) + + // A type redefined here. + typedef double bar_type; + // A type defined here (but declared abstract in the super class). + typedef char baz_type; + // A type defined only here (and not in the super class). + typedef long quux_type; + }; + + /// An external type associated to my::B. + template <typename Exact> + struct ext_vtype<category::my_cat, B<Exact>, typedef_::yin_type> + { + typedef unsigned long ret; + }; + + template <typename Exact> + struct B : public stc_get_supers(B<Exact>) + { + // Aliases. + typedef my_type_of(B, foo) foo_type; + typedef my_type_of(B, bar) bar_type; + typedef my_type_of(B, baz) baz_type; + typedef my_type_of(B, quux) quux_type; + typedef my_type_of(B, yin) yin_type; + + // Check B's vtypes. + ~B() + { + packed_vtypes< category::my_cat, B<Exact> >::ensure(); + } + }; + + + /*--------------. + | C --|> B<C>. | + `--------------*/ + + // Forward declaration. + struct C; + + // Super type. + stc_set_super(C, B<C>); + + /// Types associated to my::C. + template <> + struct vtypes<category::my_cat, C> + { + // A type defined only here (and not in the super class). + typedef double zorg_type; + }; + + struct C : public stc_get_supers(C) + { + // Aliases. + typedef my_type_of_(C, foo) foo_type; + typedef my_type_of_(C, quux) quux_type; + typedef my_type_of_(C, zorg) zorg_type; + + // Check C's vtypes. + ~C() + { + packed_vtypes<category::my_cat, C>::ensure(); + } + }; + +} // end of namespace my + + +int +main() +{ + using my::A; + using my::B; + using my::C; + + // Check exact types of A<C> and B<C>. + mlc::assert_<mlc_eq(stc::to_exact_< A<C> >::ret, C)>::check(); + mlc::assert_<mlc_eq(stc::to_exact_< B<C> >::ret, C)>::check(); + + + // Check types associated to A<C>. + mlc::assert_<mlc_eq(A<C>::foo_type, int)>::check(); + mlc::assert_<mlc_eq(A<C>::bar_type, double)>::check(); + + // Check types associated to B<C>. + mlc::assert_<mlc_eq(B<C>::baz_type, char)>::check(); + mlc::assert_<mlc_eq(B<C>::quux_type, long)>::check(); + mlc::assert_<mlc_eq(B<C>::yin_type, unsigned long)>::check(); + + mlc::assert_<mlc_eq(B<C>::bar_type, A<C>::bar_type)>::check(); + + // Check types associated to C. + mlc::assert_<mlc_eq(C::foo_type, int)>::check(); + mlc::assert_<mlc_eq(C::bar_type, double)>::check(); + mlc::assert_<mlc_eq(C::baz_type, char)>::check(); + mlc::assert_<mlc_eq(C::quux_type, long)>::check(); + mlc::assert_<mlc_eq(C::yin_type, unsigned long)>::check(); + mlc::assert_<mlc_eq(C::zorg_type, double)>::check(); +} Index: tests/Makefile.am --- tests/Makefile.am (revision 496) +++ tests/Makefile.am (working copy) @@ -14,6 +14,7 @@ multiple-supers \ super \ vtypes \ + vtypes-and-exact \ vtypes-multiple-supers any_SOURCES = any.cc @@ -22,6 +23,7 @@ multiple_supers_SOURCES = multiple-supers.cc super_SOURCES = super.cc vtypes_SOURCES = vtypes.cc +vtypes_and_exact_SOURCES = vtypes-and-exact.cc vtypes_multiple_supers_SOURCES = vtypes-multiple-supers.cc TESTS = $(check_PROGRAMS) Index: stc/vtypes.hh --- stc/vtypes.hh (revision 496) +++ stc/vtypes.hh (working copy) @@ -51,6 +51,7 @@ # include <mlc/valist.hh> # include <stc/valist_aggregator.hh> +# include <stc/exact.hh> # include <stc/internal/extract_vtype_from_list.hh> @@ -522,20 +523,22 @@ } /** End of namespace internal. */ \ \ \ - /* FIXME: Don't query from_type directly, but exact_type(from_type) */ \ - /* instead. We need mlc::any for this. */ \ + /** Entry point of the vtype retrieval algorithm. */ \ template <typename category, typename from_type, typename typedef_type> \ struct type_of_ \ { \ + /* Get the exact type of \a from_type. */ \ + typedef typename stc::to_exact_<from_type>::ret from_exact_type; \ + \ /* Look for the typedef in internal types. */ \ typedef typename \ internal::rec_get_vtype<internal::tag::internal, category, \ - from_type, typedef_type>::ret \ + from_exact_type, typedef_type>::ret \ internal_typedef; \ /* Look for the typedef as an external type. */ \ typedef typename \ internal::rec_get_vtype<internal::tag::external, category, \ - from_type, typedef_type>::ret \ + from_exact_type, typedef_type>::ret \ external_typedef; \ \ /* Did we found the virtual type? */ \