
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@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