Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
June 2006
- 2 participants
- 27 discussions
https://svn.lrde.epita.fr/svn/oln/trunk/static
ChangeLog | 14 ++++++++++++++
stc/exact.hh | 8 ++++++--
stc/vtypes.hh | 2 +-
tests/exact.cc | 14 ++++++++++++++
tests/find_exact.cc | 5 ++---
tests/vtypes-and-exact.cc | 10 +++++++---
6 files changed, 44 insertions(+), 9 deletions(-)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add stc_to_exact and stc_to_exact_ macros.
* stc/exact.hh (stc_to_exact, stc_to_exact_): New macros.
* stc/vtypes.hh (type_of_): Use the stc_to_exact macro instead
of stc::to_exact_.
* tests/exact.cc (main): Perform additional static tests.
* tests/find_exact.cc (main): Use the stc_to_exact_ macro instead
of stc::to_exact_.
* tests/vtypes-and-exact.cc (main): Likewise
Check the super classes.
(A): Use stc::any instead of stc::any__simple.
Index: stc/exact.hh
--- stc/exact.hh (révision 500)
+++ stc/exact.hh (copie de travail)
@@ -35,14 +35,18 @@
# include <mlc/bexpr.hh>
+/// \def Get the exact type of \a T.
+#define stc_to_exact(T) \
+ typename stc_to_exact_(T)
+
+#define stc_to_exact_(T) \
+ stc::to_exact_< T >::ret
# define stc_internal_is_any(T) \
mlc::bexpr_< sizeof(internal::any_select(internal::makePtr< T >())) == \
sizeof(internal::yes_) >
-
-
namespace stc
{
Index: stc/vtypes.hh
--- stc/vtypes.hh (révision 500)
+++ stc/vtypes.hh (copie de travail)
@@ -528,7 +528,7 @@
struct type_of_ \
{ \
/* Get the exact type of \a from_type. */ \
- typedef typename stc::to_exact_<from_type>::ret from_exact_type; \
+ typedef stc_to_exact(from_type) from_exact_type; \
\
/* Look for the typedef in internal types. */ \
typedef typename \
Index: tests/exact.cc
--- tests/exact.cc (révision 500)
+++ tests/exact.cc (copie de travail)
@@ -56,6 +56,20 @@
int main()
{
+ // Ensure stc::is_any_ works properly.
+ mlc::assert_< stc::is_any_< abstraction<concrete> > >::check();
+ mlc::assert_< stc::is_any_< sub_abstraction<concrete> > >::check();
+ mlc::assert_< stc::is_any_< concrete > >::check();
+
+ // Check stc_to_exact.
+ mlc::assert_<
+ mlc_eq(stc_to_exact_(abstraction<concrete>), concrete)
+ >::check();
+
+ mlc::assert_<
+ mlc_eq(stc_to_exact_(sub_abstraction<concrete>), concrete)
+ >::check();
+
//-----------------------------------------
{
Index: tests/find_exact.cc
--- tests/find_exact.cc (révision 500)
+++ tests/find_exact.cc (copie de travail)
@@ -65,7 +65,6 @@
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();
+ mlc::assert_< mlc_eq( stc_to_exact_(A< B<> >), B<stc::itself> ) >::check();
+ mlc::assert_< mlc_eq( stc_to_exact_(A<C>), C ) >::check();
}
Index: tests/vtypes-and-exact.cc
--- tests/vtypes-and-exact.cc (révision 500)
+++ tests/vtypes-and-exact.cc (copie de travail)
@@ -113,7 +113,7 @@
};
template <typename Exact>
- struct A : public stc::any__simple<Exact>
+ struct A : public stc::any<Exact>
{
// Aliases.
typedef my_type_of(A, foo) foo_type;
@@ -224,9 +224,13 @@
using my::B;
using my::C;
+ // Check super classes.
+ mlc::assert_<mlc_is_a_(C, A)>::check();
+ mlc::assert_<mlc_is_a_(C, B)>::check();
+
// 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();
+ mlc::assert_<mlc_eq(stc_to_exact_(A<C>), C)>::check();
+ mlc::assert_<mlc_eq(stc_to_exact_(B<C>), C)>::check();
// Check types associated to A<C>.
1
0
13 Jun '06
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
1
0
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. */
1
0
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 \
\
1
0
06 Jun '06
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? */ \
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/static
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Perform additional tests on simple virtual types (no multiple
inheritance nor use of stc::any).
* tests/vtypes.cc: Aesthetic changes.
(C): Rename as...
(Z): ...this.
Adjust.
(Z::bar_type, Z::baz_type, Z::yin_type): New typedefs.
(main): Check more virtual types.
vtypes.cc | 43 +++++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 18 deletions(-)
Index: tests/vtypes.cc
--- tests/vtypes.cc (revision 495)
+++ tests/vtypes.cc (working copy)
@@ -173,39 +173,42 @@
/*---.
- | C. |
+ | Z. |
`---*/
// Forward declaration.
- struct C;
+ struct Z;
- // C doesn't derive from B, but we want its vtypes to ``inherit''
+ // Z doesn't derive from B, but we want its vtypes to ``inherit''
// from B's vtypes (see the specialization
- // types<category::my_cat, C>).
+ // types<category::my_cat, Z>).
// Warning, this sugar might be removed in the future.
/// Link to B (``pseudo'' inheritance).
- stc_set_pseudosuper(C, B);
+ stc_set_pseudosuper(Z, B);
- /// Types associated to my::C.
+ /// Types associated to my::Z.
template <>
- struct vtypes<category::my_cat, C>
+ struct vtypes<category::my_cat, Z>
{
// A type defined only here (and not in the super class).
typedef double zorg_type;
};
- struct C // no inheritance
+ struct Z // no inheritance
{
// 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;
+ typedef my_type_of_(Z, foo) foo_type;
+ typedef my_type_of_(Z, bar) bar_type;
+ typedef my_type_of_(Z, baz) baz_type;
+ typedef my_type_of_(Z, quux) quux_type;
+ typedef my_type_of_(Z, yin) yin_type;
+ typedef my_type_of_(Z, zorg) zorg_type;
// Check C's vtypes.
- ~C()
+ ~Z()
{
- packed_vtypes<category::my_cat, C>::ensure();
+ packed_vtypes<category::my_cat, Z>::ensure();
}
};
@@ -220,13 +223,17 @@
mlc::assert_<mlc_eq(my::A::bar_type, mlc::int_<42>)>::check();
// Check types associated to B.
- mlc::assert_<mlc_neq(my::B::bar_type, my::A::bar_type)>::check();
mlc::assert_<mlc_eq(my::B::baz_type, char)>::check();
mlc::assert_<mlc_eq(my::B::quux_type, long)>::check();
mlc::assert_<mlc_eq(my::B::yin_type, unsigned long)>::check();
- // Check types associated to C.
- mlc::assert_<mlc_eq(my::C::foo_type, int)>::check();
- mlc::assert_<mlc_eq(my::C::quux_type, long)>::check();
- mlc::assert_<mlc_eq(my::C::zorg_type, double)>::check();
+ mlc::assert_<mlc_neq(my::B::bar_type, my::A::bar_type)>::check();
+
+ // Check types associated to Z.
+ mlc::assert_<mlc_eq(my::Z::foo_type, int)>::check();
+ mlc::assert_<mlc_eq(my::Z::bar_type, double)>::check();
+ mlc::assert_<mlc_eq(my::Z::baz_type, char)>::check();
+ mlc::assert_<mlc_eq(my::Z::quux_type, long)>::check();
+ mlc::assert_<mlc_eq(my::Z::yin_type, unsigned long)>::check();
+ mlc::assert_<mlc_eq(my::Z::zorg_type, double)>::check();
}
1
0
495: Complete the support of multiple inheritance in SCOOP w.r.t. vtype retrieval.
by Roland Levillain 06 Jun '06
by Roland Levillain 06 Jun '06
06 Jun '06
https://svn.lrde.epita.fr/svn/oln/trunk/static
Though a small test case is provided, theses new features have not
been checked thoroughly. In particular, we should provide tests known
to fail, to ensure the quality/relevance or error messages.
stc/vtypes.cc is now a complex system. I'd love to write a real
documentation for it, but I'm pretty sure it's going to evolve again
in a near future (some features might even be superfluous, like pseudo
inheritance, and dropped).
I'll try to start an embryo of documentation on Olena's Trac.
Comments welcome! :)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Complete the support of multiple inheritance in SCOOP: adjust the
algorithm of virtual type retrieval to take multiple base classes
into account.
* stc/internal/extract_vtype_from_list.hh: New file.
* stc/vtypes.hh: Include it.
(ERROR::FIRST_PARAMETER_OF_rec_get_vtype_SHOULD_BE_A_TAG): Rename
as...
(ERROR::FIRST_PARAMETER_OF_rec_get_vtype_IS_NOT_A_TAG): ...this.
(ERROR::FIRST_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_TAG)
(ERROR::THIRD_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_LIST):
New structs (error messages).
(stc_internal_maybe_get_nth_super_type): New macro.
(get_supers_list): Use it.
(maybe_super_type): Rename as...
(maybe_get_super_type): ...this.
(get_vtype): Rename as...
(get_vtype_helper): ...this.
(stc_internal_rec_get_vtype): New macro.
(rec_get_vtype_from_list): New struct.
(rec_get_vtype): Use it to rewrite the retrieval algorithm to take
multiple base classes into account.
Complete static assertions on the nature of the first parameter
(retrieval method tag).
* stc/Makefile.am (nobase_stc_HEADERS): Add
internal/extract_vtype_from_list.hh.
* tests/vtypes-multiple-supers.cc: New test.
* tests/Makefile.am (check_PROGRAMS): Add vtypes-multiple-supers.
(vtypes_multiple_supers_SOURCES): New.
* tests/vtypes.cc (packed_vtypes <category::my_cat, T>): Move this
class just after the declaration of my::cat.
stc/Makefile.am | 4
stc/internal/extract_vtype_from_list.hh | 158 +++++++++++++++++++++++
stc/vtypes.hh | 185 +++++++++++++++++++++-------
tests/Makefile.am | 4
tests/vtypes-multiple-supers.cc | 211 ++++++++++++++++++++++++++++++++
tests/vtypes.cc | 33 ++---
6 files changed, 534 insertions(+), 61 deletions(-)
Index: tests/vtypes-multiple-supers.cc
--- tests/vtypes-multiple-supers.cc (revision 0)
+++ tests/vtypes-multiple-supers.cc (revision 0)
@@ -0,0 +1,211 @@
+// 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/vtypes.hh>
+#include <mlc/cmp.hh>
+#include <mlc/assert.hh>
+#include <mlc/int.hh>
+
+// This test focuses on the support of virtual types in hierachies
+// with multiple inheritance.
+
+// FIXME: To do: Check external vtypes, too.
+
+/// 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);
+
+
+ /*----------------------.
+ | Namespace equipment. |
+ `----------------------*/
+
+ stc_equip_namespace_with_vtypes();
+
+
+ /*----------------.
+ | Various types. |
+ `----------------*/
+
+ struct alpha;
+ struct beta;
+
+
+ /*-----------.
+ | 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;
+
+ static void ensure()
+ {
+ mlc::assert_< mlc_is_ok(foo_type) >::check();
+ }
+ };
+
+
+ /*----.
+ | A. |
+ `----*/
+
+ // Forward declaration.
+ struct A;
+
+ /// Types associated to my::A.
+ template <>
+ struct vtypes<category::my_cat, my::A>
+ {
+ typedef int foo_type;
+ typedef alpha bar_type;
+ };
+
+ struct A
+ {
+ // Aliases.
+ typedef my_type_of_(A, foo) foo_type;
+ typedef my_type_of_(A, bar) bar_type;
+
+ // Check A's vtypes.
+ ~A()
+ {
+ packed_vtypes<category::my_cat, A>::ensure();
+ }
+ };
+
+
+ /*--.
+ | B |
+ `--*/
+
+ // Forward declaration.
+ struct B;
+
+ /// Types associated to my::B.
+ template <>
+ struct vtypes<category::my_cat, B>
+ {
+ typedef float foo_type;
+ typedef beta baz_type;
+ };
+
+ struct B
+ {
+ // Aliases.
+ typedef my_type_of_(B, foo) foo_type;
+ typedef my_type_of_(B, baz) baz_type;
+
+ // Check B's vtypes.
+ ~B()
+ {
+ packed_vtypes<category::my_cat, B>::ensure();
+ }
+ };
+
+
+ /*------.
+ | A B |
+ | ^ ^ |
+ | \ / |
+ | C |
+ `------*/
+
+ // Forward declaration.
+ struct C;
+
+ // Super classes.
+ stc_set_nth_super(C, 1, A);
+ stc_set_nth_super(C, 2, B);
+
+ /// Types associated to my::C.
+ template <>
+ struct vtypes<category::my_cat, C>
+ {
+ // This typedef remove the ambiguity on the `foo' vtype: this vtype
+ // is provided by both A and B. Here, let `foo' take the value from
+ // A's vtype (but we could also have chosen another value, like `int').
+ typedef my_type_of_(A, foo) foo_type;
+ };
+
+ struct C : stc_get_supers(C)
+ {
+ // Aliases.
+ typedef my_type_of_(C, foo) foo_type;
+ typedef my_type_of_(C, bar) bar_type;
+ typedef my_type_of_(C, baz) baz_type;
+
+ // Check C's vtypes.
+ ~C()
+ {
+ packed_vtypes<category::my_cat, C>::ensure();
+ }
+ };
+
+} // end of namespace my
+
+
+int
+main()
+{
+ // Check types associated to A.
+ mlc::assert_<mlc_eq(my::A::foo_type, int)>::check();
+ mlc::assert_<mlc_eq(my::A::bar_type, my::alpha)>::check();
+
+ // Check types associated to B.
+ mlc::assert_<mlc_eq(my::B::foo_type, float)>::check();
+ mlc::assert_<mlc_eq(my::B::baz_type, my::beta)>::check();
+
+ // Check types associated to C.
+ mlc::assert_<mlc_eq(my::C::foo_type, my::A::foo_type)>::check();
+ mlc::assert_<mlc_eq(my::C::bar_type, my::alpha)>::check();
+ mlc::assert_<mlc_eq(my::C::baz_type, my::beta)>::check();
+}
Index: tests/Makefile.am
--- tests/Makefile.am (revision 494)
+++ tests/Makefile.am (working copy)
@@ -13,7 +13,8 @@
exact \
multiple-supers \
super \
- vtypes
+ vtypes \
+ vtypes-multiple-supers
any_SOURCES = any.cc
entry_SOURCES = entry.cc
@@ -21,5 +22,6 @@
multiple_supers_SOURCES = multiple-supers.cc
super_SOURCES = super.cc
vtypes_SOURCES = vtypes.cc
+vtypes_multiple_supers_SOURCES = vtypes-multiple-supers.cc
TESTS = $(check_PROGRAMS)
Index: tests/vtypes.cc
--- tests/vtypes.cc (revision 494)
+++ tests/vtypes.cc (working copy)
@@ -71,6 +71,22 @@
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. |
@@ -93,22 +109,6 @@
typedef mlc::undefined baz_type;
};
- /// Packing of virtual types of any A class.
- 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();
- }
- };
-
struct A
{
// Aliases.
@@ -121,7 +121,6 @@
// packed_vtypes<category::my, A> is not checked here, since A's
// baz_type virtual type is undefined.
}
-
};
Index: stc/vtypes.hh
--- stc/vtypes.hh (revision 494)
+++ stc/vtypes.hh (working copy)
@@ -51,6 +51,8 @@
# include <mlc/valist.hh>
# include <stc/valist_aggregator.hh>
+# include <stc/internal/extract_vtype_from_list.hh>
+
/*-----------------.
| Error messages. |
@@ -62,9 +64,13 @@
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;
+ struct FIRST_PARAMETER_OF_rec_get_vtype_IS_NOT_A_TAG;
+
+ struct FIRST_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_TAG;
+ struct THIRD_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_LIST;
+
} // end of namespace stc::ERROR
} // end of namespace stc
@@ -75,10 +81,21 @@
| Equipment. |
`------------*/
+/// Internal macros, not to be used by the client.
+/// \{
+
// Note: TypedefName *must* be of the form `typedef_::foo'.
# define stc_internal_get_typedef(Type, TypedefName) \
typename TypedefName::template from_< Type >::ret
+# define stc_internal_maybe_get_nth_super_type(Type, Nth) \
+ typename internal::maybe_get_super_type< Type, Nth >::ret
+
+# define stc_internal_rec_get_vtype(Type) \
+ typename rec_get_vtype< method, category, Type, typedef_type >::ret
+
+/// \}
+
// FIXME: Complete support for hierarchies with several super classes.
@@ -112,7 +129,7 @@
namespace internal \
{ \
template <typename type, unsigned N> \
- struct maybe_super_type \
+ struct maybe_get_super_type \
{ \
typedef typename \
mlc::if_< mlc_is_a( mlc_comma_1( set_super_type<type, N> ), \
@@ -126,22 +143,22 @@
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; \
+ /* FIXME: Factor with a loop macro? */ \
+ typedef stc_internal_maybe_get_nth_super_type(type, 1) s1; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 2) s2; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 3) s3; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 4) s4; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 5) s5; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 6) s6; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 7) s7; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 8) s8; \
+ typedef stc_internal_maybe_get_nth_super_type(type, 9) s9; \
\
typedef mlc::valist_<s1, s2, s3, s4, s5, s6, s7, s8, s9> ret; \
}; \
\
\
- /* Get supers classes. */ \
+ /* Get super classes. */ \
\
namespace internal \
{ \
@@ -194,7 +211,6 @@
/* ``Pseudo'' inheritance. */ \
/* ------------------------ */ \
\
- /* FIXME: Add a multiple pseudoinheritance mechanism? */ \
template <typename type> \
struct set_pseudosuper_type \
{ \
@@ -270,21 +286,22 @@
\
} /** end of stc::internal::tag */ \
\
- \
/** Try to get \a typedef_type from \a from_type. In case this */ \
/** typedef is mlc::not_found, don't perform a recursive */ \
/** retrieval, simply return mlc::not_found. */ \
template <typename method, typename category, \
typename from_type, typename typedef_type> \
- struct get_vtype \
+ struct get_vtype_helper \
{ \
/* Nothing (no method selected). */ \
}; \
\
/** Specialization of get_vtypes for retrievals within */ \
/** internal vtypes. */ \
- template <typename category, typename from_type, typename typedef_type> \
- struct get_vtype<tag::internal, category, from_type, typedef_type> \
+ template <typename category, \
+ typename from_type, typename typedef_type> \
+ struct get_vtype_helper<tag::internal, category, \
+ from_type, typedef_type> \
{ \
/** Set of vtypes associated with FROM_TYPE. */ \
typedef vtypes<category, from_type> types; \
@@ -294,8 +311,10 @@
\
/** Specialization of get_vtypes for retrievals within */ \
/** external vtypes. */ \
- template <typename category, typename from_type, typename typedef_type> \
- struct get_vtype<tag::external, category, from_type, typedef_type> \
+ template <typename category, \
+ typename from_type, typename typedef_type> \
+ struct get_vtype_helper<tag::external, category, \
+ from_type, typedef_type> \
{ \
/** Set of vtypes associated with FROM_TYPE. */ \
typedef ext_vtype<category, from_type, typedef_type> ext_type; \
@@ -305,23 +324,46 @@
\
\
/* FIXME: Do a basic scheme of the algorithm in pseudo-code. */ \
+ \
/* FIXME: Check for mlc::undefined? */ \
\
- /** Recursive retrieval of a virtual type. */ \
+ /* Forward declaration. */ \
+ template <typename method, typename category, \
+ typename from_list, typename typedef_type> \
+ struct rec_get_vtype_from_list; \
+ \
+ /** Recursive retrieval of the virtual type \a typedef_type inside */ \
+ /** the class \a from_type. */ \
template <typename method, typename category, \
typename from_type, typename typedef_type> \
struct rec_get_vtype : \
private mlc::assert_< mlc_is_a(method, tag::method), \
- stc::ERROR::FIRST_PARAMETER_OF_rec_get_vtype_SHOULD_BE_A_TAG > \
+ stc::ERROR::FIRST_PARAMETER_OF_rec_get_vtype_IS_NOT_A_TAG > \
{ \
+ /** Get potential vtype \a typedef_type from the current class */ \
+ /** (\a from_type). */ \
typedef typename \
- get_vtype<method, category, from_type, typedef_type>::ret type; \
+ get_vtype_helper< method, category, from_type, typedef_type>::ret \
+ type; \
+ \
+ /** Implicit parents (i.e. supers), if any. */ \
+ typedef typename get_supers_list<from_type>::ret supers_list; \
+ /** Vtype deduced from the vtypes of the base class(es) of */ \
+ /** \a from_type, if any. */ \
+ typedef typename \
+ rec_get_vtype_from_list< method, category, \
+ supers_list, typedef_type >::ret \
+ vtype_from_supers; \
\
- /** Implicit parent (i.e. super), if any. */ \
- typedef stc_get_super(from_type) super; \
/** Pseudosuper class, if any. */ \
typedef stc_get_pseudosuper(from_type) pseudosuper; \
+ /** Vtype deduced from the vtype of the pseudo super class of */ \
+ /** \a from_type, if any. */ \
+ typedef typename \
+ rec_get_vtype< method, category, pseudosuper, typedef_type >::ret \
+ vtype_from_pseudo_super; \
\
+ /* Core of the search algorithm. */ \
typedef typename \
mlc::if_< \
mlc::neq_< type, mlc::not_found >, \
@@ -331,27 +373,17 @@
/* associated to FROM_TYPE) */ \
type, \
/* else */ \
- /* check if the vtype of the `super' of FROM_TYPE */ \
+ /* check if the vtypes of the `supers' of FROM_TYPE */ \
/* has the typedef */ \
typename \
- mlc::if_< mlc::neq_< typename rec_get_vtype< method, \
- category, \
- super, \
- typedef_type >::ret, \
- mlc::not_found >, \
+ mlc::if_< mlc::neq_< vtype_from_supers, mlc::not_found >, \
/* then */ \
/* return it */ \
- typename rec_get_vtype< method, \
- category, \
- super, \
- typedef_type >::ret, \
+ vtype_from_supers, \
/* else */ \
- /* check if the FROM_TYPE has a decl_parent */ \
+ /* check if the FROM_TYPE has a pseudo super */ \
/* and try to retrieve the typedef from it. */ \
- typename rec_get_vtype< method, \
- category, \
- pseudosuper, \
- typedef_type >::ret >::ret >::ret \
+ vtype_from_pseudo_super >::ret >::ret \
ret; \
}; \
\
@@ -361,20 +393,85 @@
/** Case where \a from_type = mlc::none (end of a recursive */ \
/** retrieval following `super' types). */ \
template <typename method, typename category, typename typedef_type> \
- struct rec_get_vtype<method, category, mlc::none, typedef_type> \
+ struct rec_get_vtype<method, category, mlc::none, typedef_type> : \
+ private mlc::assert_< mlc_is_a(method, tag::method), \
+ stc::ERROR::FIRST_PARAMETER_OF_rec_get_vtype_IS_NOT_A_TAG > \
{ \
typedef mlc::not_found ret; \
}; \
/** Case where \a from_type = mlc::not_found (end of a recursive */ \
/** retrieval following `super' types). */ \
template <typename method, typename category, typename typedef_type> \
- struct rec_get_vtype<method, category, mlc::not_found, typedef_type> \
+ struct rec_get_vtype<method, category, mlc::not_found, typedef_type> : \
+ private mlc::assert_< mlc_is_a(method, tag::method), \
+ stc::ERROR::FIRST_PARAMETER_OF_rec_get_vtype_IS_NOT_A_TAG > \
{ \
typedef mlc::not_found ret; \
}; \
/** \} */ \
\
\
+ /** Recursive retrieval of vtype \a typedef_type inside */ \
+ /** \a from_list. */ \
+ /** \{ */ \
+ \
+ /* Default case: \a from_type is not a mlc::valist_, abort. */ \
+ template <typename method, typename category, \
+ typename from_list, typename typedef_type> \
+ struct rec_get_vtype_from_list : \
+ private mlc::abort_< from_list, \
+ stc::ERROR::THIRD_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_LIST > \
+ { \
+ }; \
+ \
+ /** Case where the list is empty. Suprisingly, the general */ \
+ /** specialization for mlc::valist<e1, ..., e9> is not enough: */ \
+ /** this specialization is needed too. */ \
+ template <typename method, typename category, typename typedef_type> \
+ struct rec_get_vtype_from_list< \
+ method, category, mlc::valist_<>, typedef_type> \
+ { \
+ typedef mlc::not_found ret; \
+ }; \
+ \
+ /* Case where \a from_list is a genuine list. */ \
+ template <typename method, typename category, \
+ typename e1, typename e2, typename e3, \
+ typename e4, typename e5, typename e6, \
+ typename e7, typename e8, typename e9, \
+ typename typedef_type> \
+ struct rec_get_vtype_from_list< \
+ method, category, \
+ mlc::valist_<e1, e2, e3, e4, e5, e6, e7, e8, e9>, typedef_type \
+ > : \
+ private mlc::assert_< mlc_is_a(method, tag::method), \
+ stc::ERROR::FIRST_PARAMETER_OF_rec_get_vtype_from_list_IS_NOT_A_TAG > \
+ { \
+ /* For each item of the list \a from_list, perform a */ \
+ /* rec_get_vtype search. */ \
+ /* FIXME: Factor with a loop macro? */ \
+ typedef stc_internal_rec_get_vtype(e1) res1; \
+ typedef stc_internal_rec_get_vtype(e2) res2; \
+ typedef stc_internal_rec_get_vtype(e3) res3; \
+ typedef stc_internal_rec_get_vtype(e4) res4; \
+ typedef stc_internal_rec_get_vtype(e5) res5; \
+ typedef stc_internal_rec_get_vtype(e6) res6; \
+ typedef stc_internal_rec_get_vtype(e7) res7; \
+ typedef stc_internal_rec_get_vtype(e8) res8; \
+ typedef stc_internal_rec_get_vtype(e9) res9; \
+ \
+ /* Then, create a list from the results. */ \
+ typedef \
+ mlc::valist_<res1, res2, res3, res4, res5, res6, res7, res8, res9> \
+ res_list; \
+ \
+ /* Finally, match this list against a set of valid patterns. */ \
+ /* If the match fails, return mlc::not_found. */ \
+ typedef typename \
+ stc::internal::extract_vtype_from_list<res_list>::ret ret; \
+ }; \
+ \
+ \
/* ------------------------------------- */ \
/* External/internal typedef selection. */ \
/* ------------------------------------- */ \
@@ -504,6 +601,10 @@
// Get.
+// FIXME: The error message given by the compiler is not explicit
+// when trying to use stc_get_supers on a class which has no
+// (declared) super class. Improve this.
+
/** \a stc_get_supers(Type) returns a class which inerits from all the
classes declared as super types of \a Type.
Index: stc/Makefile.am
--- stc/Makefile.am (revision 494)
+++ stc/Makefile.am (working copy)
@@ -6,4 +6,6 @@
entry.hh \
exact.hh \
valist_aggregator.hh \
- vtypes.hh
+ vtypes.hh \
+ \
+ internal/extract_vtype_from_list.hh
Index: stc/internal/extract_vtype_from_list.hh
--- stc/internal/extract_vtype_from_list.hh (revision 0)
+++ stc/internal/extract_vtype_from_list.hh (revision 0)
@@ -0,0 +1,158 @@
+// 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/internal/extract_vtype_from_list.hh
+
+ \brief Match a list of types against a set of valid patterns for
+ vtype retrieval
+
+ This file is part of the rec_get_vtype_from_list from
+ stc/vtypes.hh. */
+
+#ifndef STATIC_INTERNAL_EXTRACT_VTYPE_FROM_LIST
+# define STATIC_INTERNAL_EXTRACT_VTYPE_FROM_LIST
+
+# include <mlc/flags.hh>
+# include <mlc/valist.hh>
+
+namespace stc
+{
+
+ namespace internal
+ {
+ // Shotcut, for readability purpose.
+ typedef mlc::not_found nil ;
+
+ /* FIXME: Currently, we don't distinguish these cases:
+ - a list with no vtype,
+ - a list with two vtypes or more.
+ extract_vtype_from_list returns mlc::not_found for both.
+ We probably want a distinction between these two cases, but
+ it implies handling a lot more cases in the matching. */
+
+ /** Match \a list against a set of valid patterns to extract
+ a vtype from it. Return this vtype the search succeeds,
+ otherwise return mlc::not_found. */
+ /** \{ */
+
+ /*----------------.
+ | Invalid cases. |
+ `----------------*/
+
+ /// Default case: search for a single vtype failed, because there
+ /// is more than one vtype.
+ template <typename list>
+ struct extract_vtype_from_list
+ {
+ typedef mlc::not_found ret;
+ };
+
+ /// Case where there is no vtype in the list.
+ template <>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, nil, nil, nil, nil, nil > >
+ {
+ typedef mlc::not_found ret;
+ };
+
+
+ /*--------------.
+ | Valid cases. |
+ `--------------*/
+
+ // There is one and only one valid vtype in the following
+ // patterns.
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< vtype, nil, nil, nil, nil, nil, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, vtype, nil, nil, nil, nil, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, vtype, nil, nil, nil, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, vtype, nil, nil, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, vtype, nil, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, nil, vtype, nil, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, nil, nil, vtype, nil, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, nil, nil, nil, vtype, nil > >
+ {
+ typedef vtype ret;
+ };
+
+ template <typename vtype>
+ struct extract_vtype_from_list<
+ mlc::valist_< nil, nil, nil, nil, nil, nil, nil, nil, vtype > >
+ {
+ typedef vtype ret;
+ };
+ /** \} */
+
+ } // end of namespace stc::internal
+
+} // end of namespace stc
+
+#endif // ! STATIC_INTERNAL_EXTRACT_VTYPE_FROM_LIST
1
0
05 Jun '06
https://svn.lrde.epita.fr/svn/oln/trunk/olena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Catch up with Static's support for multiple inheritance.
* oln/core/1d/grid1d.hh, oln/core/2d/grid2d.hh,
* oln/core/3d/grid3d.hh: s/stc_super_/stc_get_supers/.
* tests/image_entry.cc: Add a missing `public' qualifier for
exported types.
oln/core/1d/grid1d.hh | 2 +-
oln/core/2d/grid2d.hh | 2 +-
oln/core/3d/grid3d.hh | 2 +-
tests/image_entry.cc | 1 +
4 files changed, 4 insertions(+), 3 deletions(-)
Index: tests/image_entry.cc
--- tests/image_entry.cc (revision 493)
+++ tests/image_entry.cc (working copy)
@@ -67,6 +67,7 @@
// A very simple 1-D image.
class image : public oln::set_super_type<my::image>::ret
{
+ public:
typedef image self_type;
// Internal vtypes.
typedef oln_type_of_(self_type, grid) grid_type;
Index: oln/core/1d/grid1d.hh
--- oln/core/1d/grid1d.hh (revision 493)
+++ oln/core/1d/grid1d.hh (working copy)
@@ -57,7 +57,7 @@
};
/// A 1-dimension rectangular grid.
- struct grid1d : public stc_super_(grid1d)
+ struct grid1d : public stc_get_supers(grid1d)
{
protected:
grid1d() {}
Index: oln/core/2d/grid2d.hh
--- oln/core/2d/grid2d.hh (revision 493)
+++ oln/core/2d/grid2d.hh (working copy)
@@ -57,7 +57,7 @@
};
/// A 2-dimension rectangular grid.
- struct grid2d : public stc_super_(grid2d)
+ struct grid2d : public stc_get_supers(grid2d)
{
protected:
grid2d() {}
Index: oln/core/3d/grid3d.hh
--- oln/core/3d/grid3d.hh (revision 493)
+++ oln/core/3d/grid3d.hh (working copy)
@@ -57,7 +57,7 @@
};
/// A 3-dimension rectangular grid.
- struct grid3d : public stc_super_(grid3d)
+ struct grid3d : public stc_get_supers(grid3d)
{
protected:
grid3d() {}
1
0
05 Jun '06
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
1
0
05 Jun '06
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
{
1
0