Commit ac000e8c authored by Roland Levillain's avatar Roland Levillain
Browse files

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 Graud.
	* mlc/value.hh: Remove dead code.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@399 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 3993ecfc
2006-02-14 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 Graud.
* mlc/value.hh: Remove dead code.
2006-02-10 Thierry Geraud <theo@lrde.epita.fr>
Add implies, comma, typedef ret handling; then update.
......
......@@ -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 @@ namespace mlc
/// 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 @@ namespace mlc
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 @@ namespace mlc
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
......
......@@ -38,9 +38,15 @@ namespace mlc {
/*! \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,52 +54,151 @@ namespace mlc {
} // 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 {};
struct none : 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
** meta-code behind mlc_typedef:
** 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
......
......@@ -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>
......
......@@ -205,7 +205,7 @@ namespace mlc
/*! \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 @@ namespace mlc
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.
......
......@@ -164,23 +164,4 @@ namespace mlc {
# 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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment