https://svn.lrde.epita.fr/svn/oln/trunk/metalic
Index: ChangeLog
from Roland Levillain <roland(a)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