Commit 5993f282 authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Add documentation.

- mlc/is_a.hh (wrap): Move to...
- mlc/wrap.hh: ...this new file.
- mlc/bool.hh (ensure_): Take just one parameter; the former variadic
version is now handled by...
(ensure_list_): ...this new class.
- mlc/typedef.hh: Rename some internals.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@388 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 4495d6c7
2006-02-07 Thierry Geraud <theo@lrde.epita.fr>
Add documentation.
* mlc/is_a.hh (wrap): Move to...
* mlc/wrap.hh: ...this new file.
* mlc/bool.hh (ensure_): Take just one parameter; the former variadic
version is now handled by...
(ensure_list_): ...this new class.
* mlc/typedef.hh: Rename some internals.
2006-01-26 Roland Levillain <roland@lrde.epita.fr>
Static `if'.
......
......@@ -190,7 +190,56 @@ namespace mlc
/*! \class mlc::ensure_<expr1..>
/*! \class mlc::ensure_<expr>
**
** This class is a replacement for the instruction "expr::ensure();"
** when there is no room for having instruction. The typical use
** is to express a constraint (or several constraints) upon a
** parameter (or several parameters) of a templated class.
**
** ensure_<expr> only accepts one parameter, which has to be a
** Boolean expression type. An equivalent version for a variadic
** list of parameters is ensure_list_<expr1,..>
**
** Sample uses:
**
** template <class T>
** struct dummy : private ensure_< neq_<T, int> >
** { ...
** };
** means that T can be any type but int.
**
** template <class T1, class T2>
** struct dummy2 : private ensure_< neq_<T1, int> >,
** private ensure_< neq_<T2, float> >
** { ...
** };
** means that T1 should not be int and that T2 should not be float.
** This last example is equivalent to:
** template <class T1, class T2>
** struct dummy2 : private ensure_list_< neq_<T1, int>,
** neq_<T2, float> >
** { ...
** };
**
** Design notes: 1) This class does not derive from abstract::type
** because it is used in inheritance so a ctor should exist. 2)
** This class relies on mlc::internal::ensure_item to check that
** the expression is true.
**
** \see ensure_list_<expr1,..>
**
*/
template <typename expr>
struct ensure_ :
private internal::ensure_item<0, typename expr::internal_ensure_>
{
};
/*! \class mlc::ensure_list_<expr1..>
**
** This class is a replacement for a sequence of instructions:
** "expr1::ensure(); .." when there is no room for having
......@@ -198,9 +247,10 @@ namespace mlc
** several constraints) upon a parameter (or several parameters)
** of a templated class.
**
** ensure_<..> has a variadic list of parameters. It expects at
** least one parameter and handles up to 9 parameters. Each parameter
** has to be a Boolean expression type.
** ensure_list_<..> has a variadic list of parameters. It expects
** at least 2 parameters and handles up to 9 parameters. Each
** parameter has to be a Boolean expression type. To check only a
** single expression, the appropriate tool is ensure_<expr>.
**
** Sample uses:
**
......@@ -217,8 +267,8 @@ namespace mlc
** };
** is equivalent to:
** template <class T1, class T2>
** struct dummy2 : private ensure_< neq_<T1, int>,
** neq_<T2, int> >
** struct dummy2 : private ensure_list< neq_<T1, int>,
** neq_<T2, int> >
** { ...
** };
**
......@@ -227,10 +277,11 @@ namespace mlc
** This class relies on mlc::internal::ensure_item to check that
** each expression is true.
**
** \see ensure_<expr>
*/
template <typename expr_1,
typename expr_2 = internal::none_,
typename expr_2,
typename expr_3 = internal::none_,
typename expr_4 = internal::none_,
typename expr_5 = internal::none_,
......@@ -238,7 +289,7 @@ namespace mlc
typename expr_7 = internal::none_,
typename expr_8 = internal::none_,
typename expr_9 = internal::none_>
struct ensure_ :
struct ensure_list_ :
private internal::ensure_item<1, typename expr_1::internal_ensure_>,
private internal::ensure_item<2, typename expr_2::internal_ensure_>,
private internal::ensure_item<3, typename expr_3::internal_ensure_>,
......
......@@ -29,199 +29,227 @@
# define METALIC_IS_A_HH
# include <mlc/bool.hh>
# include <mlc/wrap.hh>
// internal macro so do not use it
# define mlc_internal_is_a__check_result_ \
sizeof(helper<T ,U >::check( (T *) helper<T,U >::makeT() )) == sizeof(mlc::internal::yes_)
// private macro so do _not_ use it
# define mlc_internal_is_a_result_ \
sizeof(helper<T,U>::select((T*)helper<T,U>::makeT())) == sizeof(yes_)
namespace mlc
{
namespace internal
namespace form
{
enum {
class_ = 1,
template_l_class_r_class_ = 2,
template_l_class_class_r_class_ = 3,
template_l_template_l_class_r_class_r_class_ = 4,
template_l_template_l_class_class_r_class_r_class_ = 5
// ...
};
//
// wrap is a workaround to fix g++-2.95 problem with implicit:
// instead of typename in <foo<T>::ret::dim>
// write <wrap<typename foo<T>::ret>::dim
template <class T> struct wrap : public T {};
template<unsigned id>
struct desc
{ char dummy[id]; };
template < class T>
static desc< class_ > of();
/// form
template < template < class > class T>
static desc< template_l_class_r_class_ > of();
namespace form
{
enum {
class_ = 1,
template_l_class_g_class_ = 2,
template_l_class_class_g_class_ = 3,
template_l_template_l_class_g_class_g_class_ = 4,
template_l_template_l_class_class_g_class_g_class_ = 5
// ...
};
template< template < class,class > class T>
static desc< template_l_class_class_r_class_ > of();
template<unsigned id>
struct desc
{ char dummy[id]; };
template < class T>
static desc< class_ > get();
template < template < class > class T>
static desc< template_l_class_g_class_ > get();
template< template < class,class > class T>
static desc< template_l_class_class_g_class_ > get();
template< template < template < class > class > class T>
static desc< template_l_template_l_class_g_class_g_class_ > get();
template< template < template < class,class > class > class T>
static desc< template_l_template_l_class_class_g_class_g_class_ > get();
// ...
template< template < template < class > class > class T>
static desc< template_l_template_l_class_r_class_r_class_ > of();
} // end of namespace mlc::internal::form
template< template < template < class,class > class > class T>
static desc< template_l_template_l_class_class_r_class_r_class_ > of();
// ...
} // end of namespace mlc::form
namespace internal
{
typedef char yes_;
struct no_ { char dummy[2]; };
// dev note : below, is_a_<T,id> is a better factorization
// dev note : below, is_a<T,id> is a better factorization
// but g++ 2.95.4 has some trouble with it
template<unsigned id>
struct is_a_;
struct is_a;
// class_
template<>
struct is_a_< form::class_ >
struct is_a< form::class_ >
{
typedef is_a_< form::class_ > self;
typedef is_a< form::class_ > self;
template<class T, class U>
struct helper
{
static yes_ check(U*);
static no_ check(...);
static yes_ select(U*);
static no_ select(...);
static T* makeT();
};
template<class T, class U>
struct check
: public bool_<( mlc_internal_is_a__check_result_ )>
struct ret
: public bool_<( mlc_internal_is_a_result_ )>
{
};
};
// template_l_class_g_class_
// template_l_class_r_class_
template<>
struct is_a_< form::template_l_class_g_class_ >
struct is_a< form::template_l_class_r_class_ >
{
typedef is_a_< form::template_l_class_g_class_ > self;
typedef is_a< form::template_l_class_r_class_ > self;
template<class T, template < class > class U>
struct helper
{
template<class V>
static yes_ check(U<V>*);
static no_ check(...);
static yes_ select(U<V>*);
static no_ select(...);
static T* makeT();
};
template<class T, template < class > class U>
struct check
: public bool_<( mlc_internal_is_a__check_result_ )>
struct ret
: public bool_<( mlc_internal_is_a_result_ )>
{
};
};
// template_l_class_class_g_class_
// template_l_class_class_r_class_
template<>
struct is_a_< form::template_l_class_class_g_class_ >
struct is_a< form::template_l_class_class_r_class_ >
{
typedef is_a_< form::template_l_class_class_g_class_ > self;
typedef is_a< form::template_l_class_class_r_class_ > self;
template<class T, template < class,class > class U>
struct helper
{
template<class V, class W>
static yes_ check(U<V,W>*);
static no_ check(...);
static yes_ select(U<V,W>*);
static no_ select(...);
static T* makeT();
};
template<class T, template < class,class > class U>
struct check
: public bool_<( mlc_internal_is_a__check_result_ )>
struct ret
: public bool_<( mlc_internal_is_a_result_ )>
{};
};
// template_l_template_l_class_g_class_g_class_
// template_l_template_l_class_r_class_r_class_
template<>
struct is_a_< form::template_l_template_l_class_g_class_g_class_ >
struct is_a< form::template_l_template_l_class_r_class_r_class_ >
{
typedef is_a_< form::template_l_template_l_class_g_class_g_class_ > self;
typedef is_a< form::template_l_template_l_class_r_class_r_class_ > self;
template<class T, template < template < class > class > class U>
struct helper
{
template<template<class> class V>
static yes_ check(U<V>*);
static no_ check(...);
static yes_ select(U<V>*);
static no_ select(...);
static T* makeT();
};
template<class T, template < template < class > class > class U>
struct check
: public bool_<( mlc_internal_is_a__check_result_ )>
struct ret
: public bool_<( mlc_internal_is_a_result_ )>
{};
};
// template_l_template_l_class_class_g_class_g_class_
// template_l_template_l_class_class_r_class_r_class_
template<>
struct is_a_< form::template_l_template_l_class_class_g_class_g_class_ >
struct is_a< form::template_l_template_l_class_class_r_class_r_class_ >
{
typedef is_a_< form::template_l_template_l_class_class_g_class_g_class_ > self;
typedef is_a< form::template_l_template_l_class_class_r_class_r_class_ > self;
template<class T, template < template < class,class > class > class U>
struct helper
{
template<template<class,class> class V>
static yes_ check(U<V>*);
static no_ check(...);
static yes_ select(U<V>*);
static no_ select(...);
static T* makeT();
};
template<class T, template < template < class,class > class > class U>
struct check
: public bool_<( mlc_internal_is_a__check_result_ )>
struct ret
: public bool_<( mlc_internal_is_a_result_ )>
{};
};
} // end of namespace mlc::internal
} // end of namespace mlc
/// Client macro mlc_is_a(T, U)
# define mlc_is_a(T, U) \
mlc::internal::wrap<typename mlc::internal::is_a_< sizeof(mlc::internal::form::get<U >()) >::check<T, U > >
/*! \macro 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
** Boolean expression type.
**
** Sample use: With:
** template <class B> struct base {};
** struct derived : public base<int> {};
** the expression mlc_is_a(derived, base) derives from mlc::true_.
** A constraint on the parameter of a class, which should be any
** subclass of base<B>, whatever B, can then be easily written:
** template <class T>
** struct foo : private mlc::ensure_< mlc_is_a(T, base) > {
** // ...
** };
**
** Limitations: 1) When U is a template class defined with a default
** parameter, the form of U is ambiguous. For instance, with the
** definition "template <class P1, class P2 = P1> struct foo {};", foo
** can be considered as well as a "template<class> class" and as a
** "template <class, class> class. The call mlc_is_a(T, foo) is thus
** ambiguous. 2) The forms of U that are handled by the meta-program
** behind the macro are limited to the few cases listed below:
** class
** template < class > class
** template < class, class > class
** template < template < class > class > class
** template < template < class, class > class > class
*/
# define mlc_is_a(T, U) \
mlc::wrap<typename mlc::internal::is_a<sizeof(mlc::form::of<U >())>::ret<T,U > >
/*! \macro 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.
**
** \see mlc_is_a(T, U)
*/
# define mlc_is_a_(T, U) \
mlc::internal::wrap< mlc::internal::is_a_< sizeof(mlc::internal::form::get<U >()) >::check<T, U > >
mlc::wrap<mlc::internal::is_a< sizeof(mlc::form::of<U >())>::ret<T,U > >
#endif // ! METALIC_IS_A_HH
......@@ -28,210 +28,211 @@
#ifndef METALIC_TYPEDEF_HH
# define METALIC_TYPEDEF_HH
# include <mlc/types.hh>
# include <mlc/flags.hh>
# include <mlc/bool.hh>
// do not use the macro below if you equip a namespace with properties
# define mlc_equip_namespace_with_typedef() \
namespace internal \
{ \
\
template <typename type, typename typedef_type> \
struct get_typedef \
{ \
typedef mlc::internal::not_found ret; \
}; \
\
template <typename type, typename typedef_type, typename cond> \
struct get_typedef_onlyif \
{ \
typedef mlc::internal::not_found ret; \
}; \
\
} \
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
/*! \macro mlc_decl_typedef (TypedefName)
/*! \macro mlc_decl_typedef(TypedefName)
**
** This macro is for declaring the use of a typedef embedded in
** classes. After having declaring a typedef, accessing the typedef
** is performed through the mlc_typedef macro. The main difference
** between the classic access, "Type::TypedefName", and its
** equivalent, "mlc_typedef(Type, TypedefName)", is that the latter
** also works when the access is ill-formed. Put differently,
** mlc_typedef also works when Type does not have TypedefName in its
** interface; the result is then the special type mlc::not_found.
**
**
** Sample use: Let us declare the "value_type" typedef name in the
** global namespace.
**
** mlc_decl_typedef(value_type);
**
** The following couple of typedef access:
**
** typename std::vector<int>::value_type
** mlc_typedef(std::vector<int>, value_type)
**
** are exactly equivalent and give "int" as result. However, with
** "type" being "std::pair<int, int>", the access:
**
** typename type::value_type
**
** is invalid and does not compile (because there is no value_type
** defined in the interface of std::pair), wheras the replacement
** access:
**
** mlc_typedef(type, value_type)
**
** does compile and gives mlc::not_found.
**
**
** When the declaration mlc_decl_typedef is located in a particular
** namespace, mlc_typedef can be used within this namespace and its
** sub-namespaces. However, it is highly recommended to define a
** particular access macro if you want to call mlc_typedef from
** another namespace (the global one for instance).
**
** namespace my {
**
** struct foo {
** typedef float value_type;
** };
**
** mlc_decl_typedef(value_type);
**
** namespace sub {
**
** template <class T>
** void bar()
** {
** mlc_typedef(foo, value_type) tmp; // ok
** }
**
** } // end of namespace my::sub
**
** } // end of namespace my
**
** int main()
** {
** {
** mlc_typedef_(my::foo, value_type) tmp; // KO
** }
** {
** using my::typedef_;
** mlc_typedef_(my::foo, value_type) tmp; // ok
** }
** }
**
** better:
**
** Macro to equip mlc with a static mechanism for a typedef retrieval.
** #define my_typedef(Type, TypedefName) mlc_typedef_in(my, Type, TypedefName)
** #define my_typedef_(Type, TypedefName) mlc_typedef_in_(my, Type, TypedefName)
**
** FIXME
** and then:
**
** int main()
** {
** my_typedef_(my::foo, value_type) tmp; // ok
** }
**
**
** Design notes:
** The declaration of a typedef name leads to the creation of the type
** "typedef_::TypedefName" located in the namespace where the
** declaration has been performed. This type can be used as a flag to
** designate a particular class typedef, whatever the classes it can
** be applied to.
**
** \see mlc_typedef(Type, TypedefName)
*/
# define mlc_decl_typedef(TypedefName) \
namespace internal \
{ \
\
namespace typedef_ \
{ \
struct TypedefName; \
} \
\
struct helper_get_typedef__##TypedefName \
{ \
typedef char yes; \
struct no { char tmp[2]; }; \
\
template <typename type, typename alias = typename type::TypedefName> \
struct run_on; \
\
template <typename type> \
static yes selector(run_on<type>*); \
\
template <typename type> \
static no selector(...); \
\
template <typename type, bool found> \
struct result; \
\
template <typename type> \
struct result <type, true> \
{ \
typedef typename type::TypedefName ret; \
}; \
\
template <typename type> \
struct result <type, false> \
{ \
typedef mlc::internal::not_found ret; \
}; \
}; \
\
template <typename type> \
struct get_typedef__##TypedefName \
{ \
typedef helper_get_typedef__##TypedefName helper_type; \
static const bool found = ( sizeof(helper_type::selector<type>(0)) == 1 ); \
typedef typename helper_type::result<type, found>::ret ret; \
}; \
\
template <typename type> \
struct get_typedef <type, typedef_::TypedefName> \
{ \
typedef typename get_typedef__##TypedefName <type> ::ret ret; \
}; \
\
\
template <typename type, bool cond> \
struct helper_get_typedef_onlyif__##TypedefName; \
\
template <typename type> \
struct helper_get_typedef_onlyif__##TypedefName <type, false> \
{ \
typedef mlc::internal::not_ok ret; \
}; \
\
template <typename type> \
struct helper_get_typedef_onlyif__##TypedefName <type, true> \
{ \
typedef typename type::TypedefName ret; \
}; \
\
template <typename type, typename cond> \
struct get_typedef_onlyif__##TypedefName \
: public helper_get_typedef_onlyif__##TypedefName <type, mlc_bool(cond)> \
{ \
typedef helper_get_typedef_onlyif__##TypedefName <type, mlc_bool(cond)> super; \
using super::ret; \
}; \
\