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