https://svn.lrde.epita.fr/svn/oln/trunk/static
ChangeLog | 9 ++
tests/tour.cc | 257 +++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 173 insertions(+), 93 deletions(-)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Document stc_find_exact and stc::itself in Static tour.
* tests/tour.cc (dynamic_hierarchy, simple_static_hierarchy):
(static_hierarchy_with_methods): Aesthetic changes.
(static_hierarchy_with_any): Rephrase comments.
(static_hierarchy_with_a_non_leaf_concrete_class): New section.
Index: tests/tour.cc
--- tests/tour.cc (révision 499)
+++ tests/tour.cc (révision 500)
@@ -29,6 +29,7 @@
/// \brief A tour of Static and SCOOP features.
# include <stc/any.hh>
+# include <stc/find_exact.hh>
// FIXME: ``Fil rouge'': building a small (but complete) static
// hierarchy, using all features from Static. Possibly, this
@@ -40,9 +41,7 @@
// having introduced the vtypes.
// FIXME: Things to show:
-// - any
// - exact
-// - find_exact
// - super
// - virtual types (and macros for super)
// - multiple super
@@ -58,46 +57,36 @@
| A small dynamic hierarchy. |
`----------------------------*/
-// Normally, we'd be writing something like this:
+/* Our first step in this tour will be the definition of a static
+ library. In classic (dynamic) OO programming, our example would
+ look like this: */
namespace dynamic_hierarchy
{
- // A is abstract.
+ // `A' is an abstract class.
struct A
{
// A virtual method.
- virtual void foo()
- {
- // ...
- }
+ virtual void foo() { /* ... */ }
// A virtual pure method.
virtual void bar() = 0;
};
- // B is abstract.
+ // `B' is a concrete class.
struct B
{
// A redefined method.
- virtual void foo()
- {
- // ...
- }
- // B::bar is defined.
- virtual void bar()
- {
- // ...
- }
+ virtual void foo() { /* ... */ }
+ // `B::bar' is defined.
+ virtual void bar() { /* ... */ }
};
- // C is concrete
+ // `C' is a concrete class.
struct C
{
- // A redefined method.
- virtual void foo()
- {
- // ...
- }
+ // `B::foo' is redefined.
+ virtual void foo() { /* ... */ }
};
} // end of namespace dynamic_hierarchy
@@ -107,16 +96,16 @@
| A small static hierarchy. |
`---------------------------*/
-// Let's start building a small static hierarchy. Converting the first
-// dynamic hierarchy results in:
-
-// FIXME: Comments.
+/* Let's start building a small static hierarchy similar to the above
+ dynamic hierarchy. */
namespace simple_static_hierarchy
{
/* In traditional OO design, a object has two types :
+
- a static type, known at compile time;
- a dynamic type or exact type, known at run time.
+
The dynamic type is more precise (or equally precise) than the
static type: it's a subclass of the static type.
@@ -128,20 +117,22 @@
In the Static C++ Object-Oriented Paradigm (SCOOP), an object
still has two types, but they are both static:
+
- the current type, which can be be an abstraction type;
- the exact type.
+
As everything is static, SCOOP must rely on the static type
system of C++, i.e, the current type must hold the information of
the exact type. This is achieved through the use of templates: a
current type embeds the exact type as a template parameter.
Consequently, in SCOOP all derivable classes of a hierarchy are
- turned into templates and have an ``Exact'' parameter, which is
- the exact static type of the object, à la Curiously Recurring
- Template Pattern (CRTP) [1].
+ turned into templates and have an `Exact' parameter, which is the
+ exact static type of the object, à la ``Curiously Recurring
+ Template Pattern'' (CRTP) [1].
Let's have a look at small example of static inheritance, with
- only two classes, A and B. */
+ only two classes, `A' and `B'. */
template <typename Exact>
struct A
@@ -152,64 +143,152 @@
{
};
- /* For instance, in the code above, A is turned into a template
- class and has an Exact parameter, and B doesn't derive from just
- A, but from A<B>. This trick allows us to write:
+ /* In the above code, `A' is turned into a template class and has an
+ `Exact' parameter, and `B' doesn't derive from just `A', but from
+ `A<B>'. This trick allows us to write:
A<B>* a = new B;
- As you can see, the current type still holds the exact type! In
- the next section, we'll see how to actually get back the exact
- type. */
+ As you can see, the current type still holds the exact type!
+ Later, we'll see how to actually get back the exact type. */
} // end of namespace simple_static_hierarchy
-/*-----------.
-| stc::any. |
-`-----------*/
+
+// ---------- //
+// stc::any. //
+// ---------- //
namespace static_hierarchy_with_any
{
/* To ease the retrieval of the exact type, we'll make use of
- stc::any. This is an instrumentation of the hierarchy to ease
+ `stc::any'. This is an instrumentation of the hierarchy to ease
the retrieval of the exact type and the conversion of the object
- to this type. In fact, there is not a single stc::any class, but
- several, which have their advantages and drawbacks w.r.t. speed,
- memory print and support for diamond inheritance. We'll only deal
- with stc::any__simple in this Static tour.
-
- stc::any is used as the base class of any top class of a static
- hierarchy: it is passed the Exact type, just like any non-leaf
- class of the hierarchy. */
+ to this type. In fact, there is not a single `stc::any' class,
+ but several, which have their advantages and drawbacks
+ w.r.t. speed, memory print and support for diamond inheritance.
+ We'll only deal with `stc::any__simple' in this Static tour:
+ where you'll see `stc::any', simply read `stc::any__simple'.
+
+ `stc::any' is used as the base class of any top class of a static
+ hierarchy. It is passed the `Exact' type, just like any non-leaf
+ class of the hierarchy (a leaf class is a class which is not
+ derived, i.e., at the bottom of an inheritance tree). */
template <typename Exact>
struct A : public stc::any__simple<Exact>
{
};
- /* Now, let's turn be into a derivable class: we only have to make
- it a template class, with an Exact parameter, and let it pass
- this exact type to A. */
+ /* Now, let's turn `B' be into a derivable class: we only have to
+ make it a template class, with an `Exact' parameter, and let it
+ pass this exact type to `A'. */
template <typename Exact>
struct B : public A<Exact>
{
};
- /* We now introduce a concrete leaf class, C, which derives from B,
- and passes its own type as exact type. */
+ /* We now introduce a concrete leaf class, `C', which derives from
+ `B', and passes its own type as exact type. */
struct C : public B<C>
{
};
-} // end of namespace static_hierarchy
+} // end of namespace static_hierarchy_with_any
-// FIXME: stc/exact.hh.
-// FIXME: stc/find_exact.hh and the non-leaf concrete classes.
-//
-// « Implicitly, our non-leaf classes are abstract. (...) »
+// ------------ //
+// stc::exact. //
+// ------------ //
+
+// FIXME: To do.
+
+
+// --------------------------- //
+// Non-leaf concrete classes. //
+// --------------------------- //
+
+/* All classes carrying an exact type are implicitly abstract classes.
+ Thus, with our current modeling, non-leaf classes are
+ compulsorily abstract. This is in compliance with good OO design
+ practices: in an class hierarchy, non-leaf classes should be
+ abstract. But what if we wanted (for a reason or another) B to be
+ a concrete (i.e., instantiable) class? The form `B<>' is not
+ allowed: a value must be provided for the `Exact' parameter. This is
+ the role of the stc::itself tag.
+
+ By convention, a class whose exact type is `B<stc::itself>' is
+ considered concrete. To shorten the coding style, non-leaf
+ concrete classes take `stc::itself' as default value for their
+ `Exact' parameter (see below). This way, `B<>' becomes a correct
+ type.
+
+ The only remaining difficulty is to pass the base class the right
+ exact type. A small metacode is required here, hidden behind the
+ `stc_find_exact' helper macro. The code below explains the
+ necessary changes. */
+
+namespace static_hierarchy_with_a_non_leaf_concrete_class
+{
+
+ /* A is left unchanged (it is still an abstract class). */
+
+ template <typename Exact>
+ struct A : public stc::any__simple<Exact>
+ {
+ };
+
+ /* B is turned into a concrete class. To achieve this, we apply two
+ changes:
+
+ 1. the parameter passed to A (B's base class) is no longer
+ `Exact', but `stc_find_exact(B, Exact)'. The `stc_find_exact'
+ macro evaluates to `B<>' (i.e., `B<stc::itself>') or to
+ `Exact', depending on whether `Exact' is equal to
+ `stc::itself' or not;
+
+ 2. `Exact' takes a default value, `stc::itself', so that one can
+ abbreviate `B<stc::itself>' to `B<>' (this change is a pure
+ matter of style and is optional). */
+
+ template <typename Exact = stc::itself>
+ struct B : public A< stc_find_exact(B, Exact) >
+ {
+ };
+
+ /* C is left unchanged. */
+
+ struct C : public B<C>
+ {
+ };
+
+ /* If we loot at the classes above C and B<> in the inheritance
+ tree, we have:
+
+ A<C> A< B<> >
+ ^ ^
+ | |
+ B<C> B<>
+ ^
+ |
+ C
+
+ The exact type is correctly passed to super classes. */
+
+} // end of namespace static_hierarchy_with_a_non_leaf_concrete_class
+
+/* To put it in a nutshell:
+
+ - non-leaf classes are abstract by default in SCOOP;
+ - to turn a non-leaf class `Foo' into a concrete class, you have to
+ - pass it `stc_find_exact(Foo, Exact)' instead of `Exact' as
+ exact type parameter to its super class;
+ - optionally (but recommended), give its `Exact' parameter a
+ default value, `stc::itself';
+ - to use such a class as a concrete one, simply use it with an empty
+ `Exact' parameter: `Foo<>'. */
// --------- //
@@ -226,48 +305,31 @@
template <typename Exact>
struct A : public stc::any__simple<Exact>
{
- // A static ``virtual'' method. Notice there is no virtual
- // keyword: the (static) dispatch is done manually through the
- // delegation to impl_foo.
- void foo()
- {
- this->exact().impl_foo();
- }
- void impl_foo()
- {
- // Empty.
- }
-
- // A virtual pure method.
- virtual void bar()
- {
- this->exact().impl_bar();
- }
- // No impl_bar, since bar is virtual pure;
+ /* Facade of a statically-dispatched method. Notice there is no
+ `virtual' keyword: the (static) dispatch is done manually
+ through the delegation to impl_foo. */
+ void foo() { this->exact().impl_foo(); }
+ // Implementation of the method.
+ void impl_foo() { /* ... */ }
+
+ // A ``virtual'' pure (i.e., abstract) method.
+ void bar() { this->exact().impl_bar(); }
+ // (No `impl_bar', since bar is abstract.)
};
template <typename Exact>
- struct B : public A<Exact>
- {
- // Redefinition.
- void impl_foo()
- {
- // Empty.
- }
- // Definition.
- void impl_bar()
+ struct B : public A< stc_find_exact(B, Exact) >
{
- // Implementation goes here.
- }
+ // A redefined method.
+ void impl_foo() { /* ... */ }
+ // B::bar (implementation) is defined.
+ void impl_bar() { /* ... */ }
};
struct C : public B<C>
{
// Redefinition.
- void impl_foo()
- {
- // Empty.
- }
+ void impl_foo() { /* ... */ }
};
} // end of namespace static_hierarchy_with_methods
@@ -281,3 +343,12 @@
[1] Coplien, James O. (1995, February). "Curiously Recurring
Template Patterns". C++ Report: 24-27. */
+
+
+
+/// Local Variables:
+/// ispell-local-dictionary: "american"
+/// End:
+
+// LocalWords: inline stc namespace vtypes OO struct CRTP typename metacode
+// LocalWords: instantiable impl ispell american
https://svn.lrde.epita.fr/svn/oln/trunk/static
ChangeLog | 4
tests/Makefile.am | 6 -
tests/tour.cc | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 292 insertions(+), 1 deletion(-)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
* tests/tour.cc: Start a Static tour.
2006-06-12 Roland Levillain <roland(a)lrde.epita.fr>
Index: tests/Makefile.am
--- tests/Makefile.am (révision 498)
+++ tests/Makefile.am (copie de travail)
@@ -16,7 +16,9 @@
super \
vtypes \
vtypes-and-exact \
- vtypes-multiple-supers
+ vtypes-multiple-supers \
+ \
+ tour
any_SOURCES = any.cc
entry_SOURCES = entry.cc
@@ -28,4 +30,6 @@
vtypes_and_exact_SOURCES = vtypes-and-exact.cc
vtypes_multiple_supers_SOURCES = vtypes-multiple-supers.cc
+tour_SOURCES = tour.cc
+
TESTS = $(check_PROGRAMS)
Index: tests/tour.cc
--- tests/tour.cc (révision 0)
+++ tests/tour.cc (révision 499)
@@ -0,0 +1,283 @@
+// 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 tests/tour.cc
+/// \brief A tour of Static and SCOOP features.
+
+# include <stc/any.hh>
+
+// FIXME: ``Fil rouge'': building a small (but complete) static
+// hierarchy, using all features from Static. Possibly, this
+// construction could be progressive, i.e., made of several attempts,
+// each enclosed in its own namespace.
+//
+// Be as simple as possible, and introduce features one by one. For
+// instance, don't introduce the multiple inheritance system after
+// having introduced the vtypes.
+
+// FIXME: Things to show:
+// - any
+// - exact
+// - find_exact
+// - super
+// - virtual types (and macros for super)
+// - multiple super
+// - entry
+
+
+// Welcome to this tour of the Static library!
+
+// FIXME: Intro.
+
+
+/*----------------------------.
+| A small dynamic hierarchy. |
+`----------------------------*/
+
+// Normally, we'd be writing something like this:
+
+namespace dynamic_hierarchy
+{
+
+ // A is abstract.
+ struct A
+ {
+ // A virtual method.
+ virtual void foo()
+ {
+ // ...
+ }
+ // A virtual pure method.
+ virtual void bar() = 0;
+ };
+
+ // B is abstract.
+ struct B
+ {
+ // A redefined method.
+ virtual void foo()
+ {
+ // ...
+ }
+ // B::bar is defined.
+ virtual void bar()
+ {
+ // ...
+ }
+ };
+
+ // C is concrete
+ struct C
+ {
+ // A redefined method.
+ virtual void foo()
+ {
+ // ...
+ }
+ };
+
+} // end of namespace dynamic_hierarchy
+
+
+/*---------------------------.
+| A small static hierarchy. |
+`---------------------------*/
+
+// Let's start building a small static hierarchy. Converting the first
+// dynamic hierarchy results in:
+
+// FIXME: Comments.
+
+namespace simple_static_hierarchy
+{
+ /* In traditional OO design, a object has two types :
+ - a static type, known at compile time;
+ - a dynamic type or exact type, known at run time.
+ The dynamic type is more precise (or equally precise) than the
+ static type: it's a subclass of the static type.
+
+ The inclusion polymorphism allows the programmer to manipulate an
+ object while knowing only it's compile time type: the type of the
+ object only needs to satisfy an interface (through inheritance)
+ required by the algorithm.
+
+
+ In the Static C++ Object-Oriented Paradigm (SCOOP), an object
+ still has two types, but they are both static:
+ - the current type, which can be be an abstraction type;
+ - the exact type.
+ As everything is static, SCOOP must rely on the static type
+ system of C++, i.e, the current type must hold the information of
+ the exact type. This is achieved through the use of templates: a
+ current type embeds the exact type as a template parameter.
+
+ Consequently, in SCOOP all derivable classes of a hierarchy are
+ turned into templates and have an ``Exact'' parameter, which is
+ the exact static type of the object, à la Curiously Recurring
+ Template Pattern (CRTP) [1].
+
+ Let's have a look at small example of static inheritance, with
+ only two classes, A and B. */
+
+ template <typename Exact>
+ struct A
+ {
+ };
+
+ struct B : public A<B>
+ {
+ };
+
+ /* For instance, in the code above, A is turned into a template
+ class and has an Exact parameter, and B doesn't derive from just
+ A, but from A<B>. This trick allows us to write:
+
+ A<B>* a = new B;
+
+ As you can see, the current type still holds the exact type! In
+ the next section, we'll see how to actually get back the exact
+ type. */
+
+} // end of namespace simple_static_hierarchy
+
+/*-----------.
+| stc::any. |
+`-----------*/
+
+namespace static_hierarchy_with_any
+{
+ /* To ease the retrieval of the exact type, we'll make use of
+ stc::any. This is an instrumentation of the hierarchy to ease
+ the retrieval of the exact type and the conversion of the object
+ to this type. In fact, there is not a single stc::any class, but
+ several, which have their advantages and drawbacks w.r.t. speed,
+ memory print and support for diamond inheritance. We'll only deal
+ with stc::any__simple in this Static tour.
+
+ stc::any is used as the base class of any top class of a static
+ hierarchy: it is passed the Exact type, just like any non-leaf
+ class of the hierarchy. */
+
+ template <typename Exact>
+ struct A : public stc::any__simple<Exact>
+ {
+ };
+
+ /* Now, let's turn be into a derivable class: we only have to make
+ it a template class, with an Exact parameter, and let it pass
+ this exact type to A. */
+
+ template <typename Exact>
+ struct B : public A<Exact>
+ {
+ };
+
+ /* We now introduce a concrete leaf class, C, which derives from B,
+ and passes its own type as exact type. */
+
+ struct C : public B<C>
+ {
+ };
+
+} // end of namespace static_hierarchy
+
+// FIXME: stc/exact.hh.
+
+// FIXME: stc/find_exact.hh and the non-leaf concrete classes.
+//
+// « Implicitly, our non-leaf classes are abstract. (...) »
+
+
+// --------- //
+// Methods. //
+// --------- //
+
+// Add the methods.
+
+// FIXME: Comments.
+
+namespace static_hierarchy_with_methods
+{
+
+ template <typename Exact>
+ struct A : public stc::any__simple<Exact>
+ {
+ // A static ``virtual'' method. Notice there is no virtual
+ // keyword: the (static) dispatch is done manually through the
+ // delegation to impl_foo.
+ void foo()
+ {
+ this->exact().impl_foo();
+ }
+ void impl_foo()
+ {
+ // Empty.
+ }
+
+ // A virtual pure method.
+ virtual void bar()
+ {
+ this->exact().impl_bar();
+ }
+ // No impl_bar, since bar is virtual pure;
+ };
+
+ template <typename Exact>
+ struct B : public A<Exact>
+ {
+ // Redefinition.
+ void impl_foo()
+ {
+ // Empty.
+ }
+ // Definition.
+ void impl_bar()
+ {
+ // Implementation goes here.
+ }
+ };
+
+ struct C : public B<C>
+ {
+ // Redefinition.
+ void impl_foo()
+ {
+ // Empty.
+ }
+ };
+
+} // end of namespace static_hierarchy_with_methods
+
+
+// FIXME: Introduce static checks of methods (kind of concept checking).
+
+int main() {}
+
+/* References:
+
+ [1] Coplien, James O. (1995, February). "Curiously Recurring
+ Template Patterns". C++ Report: 24-27. */
https://svn.lrde.epita.fr/svn/oln/trunk/static
ChangeLog | 10 +++++++
stc/Makefile.am | 1
stc/find_exact.hh | 59 +++++++++++++++++++++++++++++++++++++++++++
tests/Makefile.am | 2 +
tests/find_exact.cc | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 143 insertions(+)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add stc_find_exact.
* stc/find_exact.hh: New.
* tests/find_exact.cc (main): New test.
* stc/Makefile.am (nobase_stc_HEADERS): Add find_exact.hh.
* tests/Makefile.am (check_PROGRAMS): Add find_exact.
(find_exact_SOURCES): New.
Index: tests/find_exact.cc
--- tests/find_exact.cc (révision 0)
+++ tests/find_exact.cc (révision 0)
@@ -0,0 +1,71 @@
+// 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 <mlc/assert.hh>
+# include <mlc/is_a.hh>
+
+# include <stc/any.hh>
+# include <stc/find_exact.hh>
+# include <stc/exact.hh>
+
+namespace my
+{
+
+ /// An abstract class.
+ template <typename Exact>
+ struct A : stc::any__simple<Exact>
+ {
+ };
+
+ /// An abstract class, possibly concrete.
+ template <typename Exact = stc::itself>
+ struct B : public A< stc_find_exact(B, Exact) >
+ {
+ };
+
+ /// A concrete class.
+ struct C : public B<C>
+ {
+ };
+
+} // end of namespace my
+
+int
+main()
+{
+ using my::A;
+ using my::B;
+ using my::C;
+
+ mlc::assert_< mlc_is_a_(B<>, A) >::check();
+ mlc::assert_< mlc_is_a_(C, A) >::check();
+ mlc::assert_< mlc_is_a_(C, B) >::check();
+
+ mlc::assert_< mlc_eq(stc::to_exact_< A< B<> > >::ret,
+ B<stc::itself>) >::check();
+ mlc::assert_< mlc_eq(stc::to_exact_< A<C> >::ret, C) >::check();
+}
Index: tests/Makefile.am
--- tests/Makefile.am (révision 497)
+++ tests/Makefile.am (copie de travail)
@@ -11,6 +11,7 @@
any \
entry \
exact \
+ find_exact \
multiple-supers \
super \
vtypes \
@@ -20,6 +21,7 @@
any_SOURCES = any.cc
entry_SOURCES = entry.cc
exact_SOURCES = exact.cc
+find_exact_SOURCES = find_exact.cc
multiple_supers_SOURCES = multiple-supers.cc
super_SOURCES = super.cc
vtypes_SOURCES = vtypes.cc
Index: stc/find_exact.hh
--- stc/find_exact.hh (révision 0)
+++ stc/find_exact.hh (révision 0)
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef STATIC_FIND_EXACT_HH
+# define STATIC_FIND_EXACT_HH
+
+# define stc_find_exact(Abstraction, ExactType) \
+ typename stc::find_exact< Abstraction, ExactType >::ret
+
+namespace stc
+{
+
+ /// Special tag to be passed as exact type to make a static abstract
+ /// class ``concrete''.
+ struct itself;
+
+ /// Find the exact type for \a Abstraction whose ``Exact'' template
+ /// parameter is \a exact_type
+ template <template <class> class abstraction, typename exact_type>
+ struct find_exact
+ {
+ typedef exact_type ret;
+ };
+
+ /// Specialization for stc::itself.
+ template <template <class> class abstraction>
+ struct find_exact<abstraction, stc::itself>
+ {
+ typedef abstraction<stc::itself> ret;
+ };
+
+} // end of namespace stc
+
+
+#endif // ! STATIC_FIND_EXACT_HH
Index: stc/Makefile.am
--- stc/Makefile.am (révision 497)
+++ stc/Makefile.am (copie de travail)
@@ -5,6 +5,7 @@
any.hh \
entry.hh \
exact.hh \
+ find_exact.hh \
valist_aggregator.hh \
vtypes.hh \
\
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? */ \
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(a)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
https://svn.lrde.epita.fr/svn/oln/trunk/static
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Replace stc::internal::not_user_defined with mlc::undefined.
* stc/entry.hh (internal::not_user_defined): Remove class.
s/internal::not_user_defined/mlc::undefined/g.
entry.hh | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
Index: stc/entry.hh
--- stc/entry.hh (revision 491)
+++ stc/entry.hh (working copy)
@@ -98,6 +98,7 @@
#include <mlc/if.hh>
#include <mlc/is_a.hh>
+#include <mlc/flags.hh>
#include <mlc/comma.hh>
namespace stc
@@ -106,17 +107,15 @@
{
// End of the recurring inheritance.
struct none {};
- // No user class should derive from this class.
- struct not_user_defined {};
}
/** \brief Entry point of a hierarchy.
To be possibly specialized by the user.
- This class is use as selector ``plugging'' itself (inheriting)
+ This class is used as selector ``plugging'' itself (inheriting)
to (from) a bottom class in one of the multiple hierarchies. */
template <typename exact, unsigned num>
- struct set_entry_node : public internal::not_user_defined
+ struct set_entry_node : public mlc::undefined
{
// Nothing.
};
@@ -129,7 +128,7 @@
struct get_entry_node :
public set_entry_node<exact, num>,
public mlc::if_< mlc_is_a( mlc_comma_1( set_entry_node<exact, num + 1> ),
- internal::not_user_defined ),
+ mlc::undefined ),
internal::none,
internal::get_entry_node<exact, num + 1> >::ret
{