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