
https://svn.lrde.epita.fr/svn/oln/trunk/metalic Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add some documentation and types to Metalic. * mlc/cmp.hh: More documentation. (is_found, is_not_found, is_ok): New. * mlc/implies.hh, mlc/is_a.hh: Fix Doxygen comment. * mlc/flags.hh: More documentation. (dummy, locked): New. From Thierry G�raud. * mlc/value.hh: Remove dead code. cmp.hh | 35 ++++++++++++-- flags.hh | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- implies.hh | 4 - is_a.hh | 4 - value.hh | 19 ------- 5 files changed, 162 insertions(+), 49 deletions(-) Index: mlc/implies.hh --- mlc/implies.hh (revision 398) +++ mlc/implies.hh (working copy) @@ -31,9 +31,9 @@ # include <mlc/bool.hh> -/*! \macro mlc_implies(Left_BExpr, Right_BExpr) +/*! \def mlc_implies(Left_BExpr, Right_BExpr) ** -** Macro correponding to mlc::implies_<L, R>, for use in a template +** Macro corresponding to mlc::implies_<L, R>, for use in a template ** context. ** ** \see mlc::implies_<L, R> Index: mlc/is_a.hh --- mlc/is_a.hh (revision 398) +++ mlc/is_a.hh (working copy) @@ -205,7 +205,7 @@ -/*! \macro mlc_is_a(T, U) +/*! \def mlc_is_a(T, U) ** ** Macro that answers if T is an U. T should be a type and U can have ** different forms: class, template class, etc. The result is a @@ -240,7 +240,7 @@ mlc::wrap_<typename mlc::internal::is_a<sizeof(mlc::form::of<U >())>::ret<T,U > > -/*! \macro mlc_is_a_(T, U) +/*! \def mlc_is_a_(T, U) ** ** Macro equivalent as mlc_is_a(T, U) for use in a non templated ** context. The result is a Boolean expression type. Index: mlc/flags.hh --- mlc/flags.hh (revision 398) +++ mlc/flags.hh (working copy) @@ -38,9 +38,15 @@ /*! \class mlc::abstract::flag ** - ** Abstract base class for types that are only flags. + ** Abstract base class for types that are flags. A flag type + ** expresses a particular property translated by the name of the + ** type. For instance, mlc::undefined is a flag type which + ** means "declared but not defined". ** - ** Example: mlc::undefined is a mlc::abstract::flag. + ** Flag types have no interface; they only serve as types. + ** + ** The flags provided in mlc are: dummy, locked, none, not_found, + ** undefined, and unknown. */ struct flag : public type {}; @@ -48,37 +54,91 @@ } // end of namespace mlc::abstract - /*! \class mlc::undefined + /*! \class mlc::dummy ** - ** Flag class to state that a type is undefined, that is, declared - ** but not defined. + ** Flag class to value a type when one knows that this value does + ** not matter and will not be used. ** - ** Sample use: you want to define a trait to get the signed version - ** of a type T. For that, you write: + ** The dummy type appears typically in some part of meta-program + ** that are ignored. In mlc_typedef_onlyif, for instance, dummy is + ** returned when the guard value is false. When defining a + ** pattern matching meta-program, if a clause is not a match, the + ** returned type for this clause is evaluated into dummy. + */ + struct dummy : public abstract::flag {}; + + + /*! \class mlc::locked + ** + ** Flag class whose purpose is to state and ensure that a type + ** should not be re-defined (or specialized) by the client. + ** + ** Let us consider a type that should not be re-defined or + ** specialized by the client. Such a type is defined having + ** mlc::locked as base class. Inserting the static check + ** mlc_is_a(type, locked) then ensures that this type is untouched. + ** + ** Sample use: First a type (set_foo) is declared for the user to + ** specialize it: + ** + ** template <typename T> struct set_foo; + ** + ** and the access to this specialization (handled by the type + ** get_foo), for use in a meta-program, is written once for all. + ** The access code should not be re-defined by the client so it is + ** tagged as locked: ** ** template <typename T> - ** struct signed_type_of - ** { - ** typedef mlc::undefined ret; + ** struct get_foo : public mlc::locked, + ** public set_foo<T> { + ** using set_foo<T>::ret; ** }; ** - ** which means that the return type (ret) is not defined by default. - ** Put differently, this trait is just declared. So far, the - ** type "signed_type_of<unsigned short>::ret" is "mlc::undefined". - ** - ** Other flags are mlc::unknown, mlc::none, and mlc::not_found. + ** The meta-program that reads the value of get_foo<T>::ret also + ** checks that get_foo<T> derives from mlc::locked. That thus + ** ensures that the client has not confuse set_foo with get_foo. */ - struct undefined : public abstract::flag {}; + struct locked : public abstract::flag {}; - struct unknown : public abstract::flag {}; + /*! \class mlc::none + ** + ** Flag class to state that there is no type corresponding to a + ** request. + ** + ** Sample use 1: In the context of a variadic parameter list, none + ** is the default value for every parameter after the first one. + ** + ** With: + ** template <typename P1, + ** typename P2 = none, + ** typename P3 = none> + ** struct foo { + ** typedef P1 param1; + ** typedef P2 param2; + ** typedef P3 param3; + ** }; + ** + ** instantiated into foo<int, float>, we thus have param3 set to + ** none. + ** + ** Sample use 2: The type none can be used as a trait value. For + ** instance: + ** + ** template<> + ** struct super_type_of <int> { + ** typedef none ret; + ** }; + */ struct none : public abstract::flag {}; /*! \class mlc::not_found ** - ** Flag class to state that a type is not found (for use in the - ** context of trying to retrieve a type). + ** Flag class to state that a type is not found. This class is for + ** use in the context of trying to retrieve a type. More precisely, + ** this flag type should only appear as a return of a piece of + ** meta-program. ** ** Design issue: this flag is used in some meta-code to handle the ** case of an "absent" typedef. For instance it is used in the @@ -86,14 +146,59 @@ ** mlc_typedef(std::vector<int>, value_type) is int, whereas ** mlc_typedef(std::vector<int>, walue_type) is mlc::not_found. ** - ** Other flags are mlc::undefined, mlc::unknown, and mlc::none. - ** ** \see mlc_typedef */ struct not_found : public abstract::flag {}; - // FIXME: add corresponding is_* types + /*! \class mlc::undefined + ** + ** Flag class to state that a type is undefined, that is, declared + ** but not defined. + ** + ** Sample use: When you want to define a trait to get the signed + ** version of a type T, you write: + ** + ** template <typename T> + ** struct signed_type_of + ** { + ** typedef mlc::undefined ret; + ** }; + ** + ** meaning that the return type (ret) is not defined by default. + ** Put differently, this trait is just declared. So far, the trait + ** value signed_type_of<unsigned short>::ret is mlc::undefined. If + ** it happens that this trait value is not specialized in some + ** following code, this value thus remains mlc::undefined, which + ** clearly denotes an error. + ** + ** \see mlc::abstract::flag. + */ + struct undefined : public abstract::flag {}; + + + /*! \class mlc::unknown + ** + ** Flag class to state that a result is yet unknown. + ** + ** Sample use: This flag can be used in a meta-program to express + ** that a sub-program fails to give the expected result. For + ** instance in: + ** + ** template <class T> + ** struct foo { + ** typedef sub_program_1 ret1; + ** typedef sub_program_2 ret2; + ** typedef typename if_< neq_<ret1, unknown>, + ** ret1, + ** ret2 >::ret ret; + ** }; + */ + struct unknown : public abstract::flag {}; + + + // FIXME: Doc. + struct not_ok : public abstract::flag {}; } // end of namespace mlc Index: mlc/value.hh --- mlc/value.hh (revision 398) +++ mlc/value.hh (working copy) @@ -164,23 +164,4 @@ # include <mlc/bool.hh> -// FIXME: the following code causes inclusion recursion... - -// # include <mlc/is_a.hh> - -// namespace mlc { - -// template <typename T> -// struct is_value : public mlc_is_a(T, mlc::abstract::value) -// { -// }; - -// template <typename T> -// struct is_not_value : public not_<mlc_is_a(T, mlc::abstract::value)> -// { -// }; - -// } // end of namespace mlc - - #endif // ! METALIC_VALUE_HH Index: mlc/cmp.hh --- mlc/cmp.hh (revision 398) +++ mlc/cmp.hh (working copy) @@ -39,13 +39,14 @@ namespace mlc { - // FIXME: code moved from the end of value.hh + /// Check whether \a T is a mlc::abstract::value. template <typename T> struct is_value : public mlc_is_a(T, mlc::abstract::value) { }; + /// Check whether \a T is not a mlc::abstract::value. template <typename T> struct is_not_value : public not_<mlc_is_a(T, mlc::abstract::value)> { @@ -54,7 +55,7 @@ /// Equality test between a couple of types. - + /// \{ template <typename T1, typename T2> struct eq_ : private ensure_list_< is_not_value<T1>, is_not_value<T2> >, @@ -67,10 +68,10 @@ public true_ { }; - + /// \} /// Inequality test between a couple of types. - + /// \{ template <typename T1, typename T2> struct neq_ : private ensure_list_< is_not_value<T1>, is_not_value<T2> >, @@ -83,7 +84,33 @@ public false_ { }; + /// \} + + + /*--------------------------------------. + | Syntactic sugar for flag comparison. | + `--------------------------------------*/ + + /// Shortcuts for comparison with mlc::not_found. + /// \{ + template <typename T> + struct is_found : public neq_<T, not_found> + { + }; + + template <typename T> + struct is_not_found : public neq_<T, not_found> + { + }; + /// \} + + /// Check whether a type is a sound (supposedly before using it). + struct is_ok : public ands_< neq_<T, not_found>, + neq_<T, not_ok>, + neq_<T, undefined > > + { + }; } // end of namespace mlc