https://svn.lrde.epita.fr/svn/oln/trunk/static
The support for multiple inheritance in SCOOP is not complete: the mechanism for retrieving virtual types queries only the first base class, not the (possible) other ones.
Index: ChangeLog from Roland Levillain roland@lrde.epita.fr
Allow multiple super classes in SCOOP's static hierarchies.
* stc/valist_aggregator.hh: New. * stc/vtypes.hh: Include it. (ERROR::PARAMETER_OF_get_super_types_helper_IS_NOT_A_VALID_VALIST): New struct. (set_super_type): Inherit from mlc::undefined by default. (internal::maybe_super_type, get_supers_list) (internal::get_super_types_helper, get_super_types) (rec_get_vtype): s/stc_super/stc_get_super/. s/stc_pseudosuper/stc_get_pseudosuper/. (stc_set_super): Remove previous definition of this macro, and make it a shortcut for... (stc_set_nth_super): ...this one (new). (stc_get_supers, stc_get_nth_super_, stc_get_nth_super_) (stc_get_super_, stc_get_super_): New macros. (stc_super, stc_super_): Remove macros. (stc_pseudosuper, stc_pseudosuper_): Rename macros as... (stc_get_pseudosuper, stc_get_pseudosuper_): ...these. * tests/super.cc, tests/multiple-supers.cc: New tests. * tests/vtypes.cc: s/stc_get_supers_/stc_get_supers/g. * stc/Makefile.am (nobase_stc_HEADERS): Add exact.hh and valist_aggregator.hh. * tests/Makefile.am (check_PROGRAMS): Add multiple-supers, super. (multiple_supers_SOURCES, super_SOURCES): New.
stc/Makefile.am | 2 stc/valist_aggregator.hh | 138 ++++++++++++++++++++++++++++++++ stc/vtypes.hh | 199 ++++++++++++++++++++++++++++++++++++++++------- tests/Makefile.am | 4 tests/multiple-supers.cc | 109 +++++++++++++++++++++++++ tests/super.cc | 97 ++++++++++++++++++++++ tests/vtypes.cc | 4 7 files changed, 524 insertions(+), 29 deletions(-)
Index: tests/super.cc --- tests/super.cc (revision 0) +++ tests/super.cc (revision 0) @@ -0,0 +1,97 @@ +// 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. + +// Check Static's super relationship. + +#include <stc/vtypes.hh> +#include <mlc/is_a.hh> +#include <mlc/assert.hh> + + +namespace my +{ + + /*----------------------. + | Namespace equipment. | + `----------------------*/ + + stc_equip_namespace_with_vtypes(); + + + /*----. + | A. | + `----*/ + + struct A + { + }; + + + /*------------. + | B ---|> A. | + `------------*/ + + // Forward declaration. + struct B; + + // Warning, this sugar might be removed in the future. + stc_set_super(B, A); + + struct B : public stc_get_supers(B) + { + }; + + + /*---. + | C. | + `---*/ + + // Forward declaration. + struct C; + + /* C doesn't derive from B, but we want its vtypes to ``inherit'' + from B's vtypes. Note that there are actually no vtypes in this + simple test, but it doesn't matter: we are only checking the + super relationship here. */ + + // Warning, this sugar might be removed in the future. + /// Link to B (``pseudo'' inheritance). + stc_set_pseudosuper(C, B); + + struct C // no inheritance + { + }; + +} // end of namespace my + + +int +main() +{ + mlc::assert_<mlc_is_a_(my::B, my::A)>::check(); + mlc::assert_<mlc_is_not_a_(my::C, my::A)>::check(); +}
Property changes on: tests/exact.cc ___________________________________________________________________ Name: svn:executable - *
Index: tests/Makefile.am --- tests/Makefile.am (revision 492) +++ tests/Makefile.am (working copy) @@ -11,11 +11,15 @@ any \ entry \ exact \ + multiple-supers \ + super \ vtypes
any_SOURCES = any.cc entry_SOURCES = entry.cc exact_SOURCES = exact.cc +multiple_supers_SOURCES = multiple-supers.cc +super_SOURCES = super.cc vtypes_SOURCES = vtypes.cc
TESTS = $(check_PROGRAMS) Index: tests/vtypes.cc --- tests/vtypes.cc (revision 492) +++ tests/vtypes.cc (working copy) @@ -156,7 +156,7 @@ typedef unsigned long ret; };
- struct B : public stc_super_(B) + struct B : public stc_get_supers(B) { // Aliases. typedef my_type_of_(B, foo) foo_type; @@ -210,7 +210,7 @@ } };
-} +} // end of namespace my
int Index: tests/multiple-supers.cc --- tests/multiple-supers.cc (revision 0) +++ tests/multiple-supers.cc (revision 0) @@ -0,0 +1,109 @@ +// 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. + +// Check Static's multiple super relationship. + +#include <stc/vtypes.hh> +#include <mlc/is_a.hh> +#include <mlc/assert.hh> + + +namespace my +{ + + /*----------------------. + | Namespace equipment. | + `----------------------*/ + + stc_equip_namespace_with_vtypes(); + + + /*--. + | A | + `--*/ + + struct A + { + }; + + + /*--. + | B | + `--*/ + + struct B + { + }; + + + /*--. + | A | + | ^ | + | | | + | C | + `--*/ + + // Forward declaration. + struct C; + + // Warning, this sugar might be removed in the future. + stc_set_super(C, A); + + struct C : public stc_get_supers(C) + { + }; + + + /*------. + | A B | + | ^ ^ | + | \ / | + | D | + `------*/ + + // Forward declaration. + struct D; + + // Warning, this sugar might be removed in the future. + stc_set_nth_super(D, 1, A); + stc_set_nth_super(D, 2, B); + + struct D : public stc_get_supers(D) + { + }; + +} // end of namespace my + + +int +main() +{ + mlc::assert_<mlc_is_a_(my::C, my::A)>::check(); + + mlc::assert_<mlc_is_a_(my::D, my::A)>::check(); + mlc::assert_<mlc_is_a_(my::D, my::B)>::check(); +}
Property changes on: stc/exact.hh ___________________________________________________________________ Name: svn:executable - *
Index: stc/valist_aggregator.hh --- stc/valist_aggregator.hh (revision 0) +++ stc/valist_aggregator.hh (revision 0) @@ -0,0 +1,138 @@ +// 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. + +/// \file stc/valist_aggregator.hh +/// \brief Super class aggregation mechanism. +/// +/// Converts a mlc::valist_ into a class inheriting from all the +/// elements of the list. + +#ifndef STATIC_VALIST_AGGREGATOR_HH +# define STATIC_VALIST_AGGREGATOR_HH + +// FIXME: To be moved in Metalic? + +// FIXME: Propose a version where inheritance is virtual (with an +// optional fine-grained version, where `virtual' presence can be +// choose individually for each element?) + +#include <mlc/abort.hh> +#include <mlc/valist.hh> + +namespace stc +{ + namespace ERROR + { + + struct PARAMETER_OF_internal_valist_aggregator_OUT_OF_BOUNDS; + + } // end of namespace stc::ERROR + + + // There is a lot a redundant code here; the Boost Preprocessor + // Library would be a nice solution, but we don't want to depend on + // third-party libraries. + + + /// Defaut version: abort. + template <typename super_list> + struct valist_aggregator : + private mlc::abort_< + super_list, + stc::ERROR::PARAMETER_OF_internal_valist_aggregator_OUT_OF_BOUNDS + > + { + }; + + /// Version for 2 super classes. + template <typename E1, typename E2> + struct valist_aggregator< mlc::valist_ <E1,E2> > : + public E1, 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 + { + }; + + /// 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 + { + }; + + /// 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 + { + }; + + /// Version for 6 super classes. + 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 + { + }; + + /// Version for 7 super classes. + 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 + { + }; + + /// Version for 8 super classes. + 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 + { + }; + + /// Version for 9 super classes. + 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 + { + }; + /// } + +} // end of namespace stc + +#endif // ! STATIC_VALIST_AGGREGATOR_HH Index: stc/vtypes.hh --- stc/vtypes.hh (revision 492) +++ stc/vtypes.hh (working copy) @@ -36,11 +36,20 @@ # include <mlc/flags.hh> # include <mlc/typedef.hh> # include <mlc/ret.hh> + +# include <mlc/assert.hh> +# include <mlc/abort.hh> + # include <mlc/bool.hh> +# include <mlc/int.hh> + # include <mlc/cmp.hh> # include <mlc/if.hh> # include <mlc/is_a.hh> -# include <mlc/assert.hh> + +# include <mlc/comma.hh> +# include <mlc/valist.hh> +# include <stc/valist_aggregator.hh>
/*-----------------. @@ -52,8 +61,12 @@ /// Error messages raised by static assertions. namespace ERROR { + struct FIRST_PARAMETER_OF_rec_get_vtype_SHOULD_BE_A_TAG; + struct PARAMETER_OF_get_super_types_helper_IS_NOT_A_VALID_VALIST; + } // end of namespace stc::ERROR + } // end of namespace stc
@@ -66,7 +79,11 @@ # define stc_internal_get_typedef(Type, TypedefName) \ typename TypedefName::template from_< Type >::ret
-// FIXME: Add support for hierarchies with several super classes. + +// FIXME: Complete support for hierarchies with several super classes. + +// FIXME: Could we extract some classes from this gigantic macro? + # define stc_equip_namespace_with_vtypes() \ \ /* ----------------------- */ \ @@ -81,17 +98,103 @@ /* Inheritance. */ \ /* ------------- */ \ \ - template <typename type> \ - struct set_super_type \ + /* Set super classes. */ \ + \ + template<typename type, unsigned N = 1> \ + struct set_super_type : public mlc::undefined \ { \ typedef mlc::none ret; \ }; \ \ \ + /* Get supers list. */ \ + \ + namespace internal \ + { \ + template <typename type, unsigned N> \ + struct maybe_super_type \ + { \ + typedef typename \ + mlc::if_< mlc_is_a( mlc_comma_1( set_super_type<type, N> ), \ + mlc::undefined ), \ + mlc::internal::valist_none, \ + mlc_ret(mlc_comma_1(set_super_type< type, N >)) >::ret \ + ret; \ + }; \ + } /* end of namespace internal */ \ + \ + template <typename type> \ + struct get_supers_list \ + { \ + /* FIXME: Factor with a macro? */ \ + typedef typename internal::maybe_super_type<type, 1>::ret s1; \ + typedef typename internal::maybe_super_type<type, 2>::ret s2; \ + typedef typename internal::maybe_super_type<type, 3>::ret s3; \ + typedef typename internal::maybe_super_type<type, 4>::ret s4; \ + typedef typename internal::maybe_super_type<type, 5>::ret s5; \ + typedef typename internal::maybe_super_type<type, 6>::ret s6; \ + typedef typename internal::maybe_super_type<type, 7>::ret s7; \ + typedef typename internal::maybe_super_type<type, 8>::ret s8; \ + typedef typename internal::maybe_super_type<type, 9>::ret s9; \ + \ + typedef mlc::valist_<s1, s2, s3, s4, s5, s6, s7, s8, s9> ret; \ + }; \ + \ + \ + /* Get supers classes. */ \ + \ + namespace internal \ + { \ + \ + /** Accessor helper. */ \ + template<typename type> \ + struct get_super_types_helper; \ + \ + /** Accessor helper: specialization for the case of a single */ \ + /** super class. */ \ + template<typename super> \ + struct get_super_types_helper< mlc::valist_ <super> > \ + { \ + /** Return the super class directly. */ \ + typedef super ret; \ + }; \ + \ + /** Accessor helper: specializations for the case of two super */ \ + /** classes or more. */ \ + template <typename super1, typename super2, typename super3> \ + struct get_super_types_helper< mlc::valist_ <super1, super2, super3> > \ + { \ + /** Return an aggregate of the super classes. */ \ + typedef stc::valist_aggregator< mlc::valist_ <super1, super2, super3> > \ + ret; \ + }; \ + \ + /** Accessor helper: default case (abort). */ \ + template<typename type> \ + struct get_super_types_helper : \ + public mlc::abort_< \ + type, \ + stc::ERROR::PARAMETER_OF_get_super_types_helper_IS_NOT_A_VALID_VALIST \ + > \ + { \ + }; \ + \ + } /* end of namespace internal */ \ + \ + \ + template<typename type> \ + struct get_super_types \ + { \ + typedef typename get_supers_list<type>::ret supers_list; \ + typedef typename internal::get_super_types_helper<supers_list>::ret ret; \ + }; \ + \ + \ /* ------------------------ */ \ /* ``Pseudo'' inheritance. */ \ /* ------------------------ */ \ \ + /* FIXME: Add a multiple pseudoinheritance mechanism? */ \ template <typename type> \ struct set_pseudosuper_type \ { \ @@ -215,9 +318,9 @@ get_vtype<method, category, from_type, typedef_type>::ret type; \ \ /** Implicit parent (i.e. super), if any. */ \ - typedef stc_super(from_type) super; \ + typedef stc_get_super(from_type) super; \ /** Pseudosuper class, if any. */ \ - typedef stc_pseudosuper(from_type) pseudosuper; \ + typedef stc_get_pseudosuper(from_type) pseudosuper; \ \ typedef typename \ mlc::if_< \ @@ -376,17 +479,64 @@ | Macros. | `---------*/
-/* FIXME: I don't know whether this macro will be really usable; what +// ------------- // +// Inheritance. // +// ------------- // + +// Set. + +/* FIXME: I don't know whether these macros will be really usable; what if Type is a template class? We would have to provide additional - versions of this macro, with support for one parameter, two + versions of these macros, with support for one parameter, two parameters, etc. */ /// \def Declare the immediate base class \a Super of \a Type. -# define stc_set_super(Type, Super) \ +#define stc_set_nth_super(Type, N, Super) \ template <> \ - struct set_super_type<Type> \ + struct set_super_type< Type, N > \ { \ typedef Super ret; \ - } + }; + +// Shortcut. +#define stc_set_super(Type, Super) \ + stc_set_nth_super(Type, 1, Super) + + +// Get. + +/** \a stc_get_supers(Type) returns a class which inerits from all the + classes declared as super types of \a Type. + + However, there is an exception when Type as single super: + stc_get_supers returns this super class directly, not a class + ineriting from it, to avoid a useless indirection. */ +#define stc_get_supers(Type) \ + get_super_types< Type >::ret + +/// \def Get the Nth immediate base class(es) of Type (version to be +/// used inside a template). +# define stc_get_nth_super(Type, Nth) \ + typename stc_get_nth_super_(Type, Nth) + +/// \def Get the Nth immediate base class(es) of Type (version to be +/// used outside a template). +# define stc_get_nth_super_(Type, Nth) \ + set_super_type< Type, Nth >::ret + +/// \def Get the fisrt immediate base class of Type (version to be +/// used inside a template). +# define stc_get_super(Type) \ + typename stc_get_super_(Type) + +/// \def Get the first immediate base class of Type (version to be +/// used outside a template). +# define stc_get_super_(Type) \ + stc_get_nth_super_(Type, 1) + + +// -------------------- // +// Pseudo inheritance. // +// -------------------- //
/* FIXME: I don't know whether this macro will be really usable; what if Type is a template class? We would have to provide additional @@ -400,25 +550,20 @@ typedef PseudoSuper ret; \ }
-/// \def Get the immediate base class of T (version to be used inside -/// a template). -# define stc_super(T) \ - typename stc_super_(T) - -/// \def Get the immediate base class of T (version to be used outside -/// a template). -# define stc_super_(T) \ - set_super_type<T>::ret - -/// \def Get the pseudosuper class of T (version to be used inside a +/// \def Get the pseudosuper class of Type (version to be used inside a /// template). -# define stc_pseudosuper(T) \ - typename stc_pseudosuper_(T) +# define stc_get_pseudosuper(Type) \ + typename stc_get_pseudosuper_(Type)
-/// \def Get the pseudosuper class of T (version to be used outside a +/// \def Get the pseudosuper class of Type (version to be used outside a /// template). -# define stc_pseudosuper_(T) \ - set_pseudosuper_type<T>::ret +# define stc_get_pseudosuper_(Type) \ + set_pseudosuper_type< Type >::ret + + +// ---------------------- // +// Virtual types access. // +// ---------------------- //
// FIXME: Perhaps only ``external'' (i.e., non local) versions of // stc_type_of are really useful (since they are more precise), and we Index: stc/Makefile.am --- stc/Makefile.am (revision 492) +++ stc/Makefile.am (working copy) @@ -4,4 +4,6 @@ nobase_stc_HEADERS = \ any.hh \ entry.hh \ + exact.hh \ + valist_aggregator.hh \ vtypes.hh