https://svn.lrde.epita.fr/svn/oln/trunk/metalic
Index: ChangeLog
from Thierry Geraud <theo(a)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.
bool.hh | 65 +++++++++++--
is_a.hh | 160 +++++++++++++++++++-------------
typedef.hh | 297 ++++++++++++++++++++++++++++++-------------------------------
wrap.hh | 121 ++++++++++++++++++++++++
4 files changed, 422 insertions(+), 221 deletions(-)
Index: mlc/wrap.hh
--- mlc/wrap.hh (revision 0)
+++ mlc/wrap.hh (revision 0)
@@ -0,0 +1,121 @@
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 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, 59 Temple Place - Suite 330, 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.
+
+#ifndef METALIC_WRAP_HH
+# define METALIC_WRAP_HH
+
+
+namespace mlc
+{
+ /*! \class mlc::wrap<T>
+ **
+ ** This class is a workaround to the problem of implicit typename
+ ** that appears when writting something like:
+ ** outer_struct::inner_struct::value
+ **
+ ** Instead of solving manually this problem with:
+ ** typedef typename outer_struct::inner_struct temp;
+ ** temp::value
+ ** you can write directly:
+ ** wrap< typename outer_struct::inner_struct >::value
+ **
+ ** This class is used by the mlc_is_a macro.
+ **
+ ** Design note: a detailed example can be read at the end of
+ ** the file mlc/wrap.hh
+ */
+
+ template <class T>
+ struct wrap : public T
+ {
+ typedef T unwrap;
+ };
+
+} // end of namespace mlc
+
+
+/*
+
+// FIXME: the code below is weird! I didn't succeed in reproducing
+// the limitation of the "implicit typename" error; see the comment in
+// code...
+
+#include <iostream>
+#include <mlc/bool.hh>
+
+template <class T> struct wrap : public T {};
+
+namespace my
+{
+ template <class T, T val>
+ struct value_
+ {
+ static const T value = val;
+ };
+
+ template <bool b>
+ struct value_ <bool, b>
+ {
+ static const bool value = b;
+ };
+
+ template <bool b>
+ struct bool_;
+
+ template <>
+ struct bool_<true> : public value_<bool, true>
+ {
+ };
+
+ typedef bool_<true> true_;
+}
+
+template <class T>
+struct outer
+{
+ struct inner_struct
+ : public my::true_ {
+ // replacing "my" by "mlc" gives an error (see KO below) and I
+ // don't understand why!
+ };
+};
+
+template <class T>
+void foo_()
+{
+ std::cout << outer<T>::inner_struct::value << std::endl; // KO
+}
+
+int main()
+{
+ foo_<int>();
+}
+
+*/
+
+
+#endif // ! METALIC_WRAP_HH
Index: mlc/bool.hh
--- mlc/bool.hh (revision 387)
+++ mlc/bool.hh (working copy)
@@ -190,7 +190,56 @@
- /*! \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 @@
** 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,7 +267,7 @@
** };
** is equivalent to:
** template <class T1, class T2>
- ** struct dummy2 : private ensure_< neq_<T1, int>,
+ ** struct dummy2 : private ensure_list< neq_<T1, int>,
** neq_<T2, int> >
** { ...
** };
@@ -227,10 +277,11 @@
** 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 @@
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_>,
Index: mlc/is_a.hh
--- mlc/is_a.hh (revision 387)
+++ mlc/is_a.hh (working copy)
@@ -29,37 +29,25 @@
# 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
- {
-
- //
- // 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 {};
-
-
- /// form
-
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_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
// ...
};
@@ -68,160 +56,200 @@
{ char dummy[id]; };
template < class T>
- static desc< class_ > get();
+ static desc< class_ > of();
template < template < class > class T>
- static desc< template_l_class_g_class_ > get();
+ static desc< template_l_class_r_class_ > of();
template< template < class,class > class T>
- static desc< template_l_class_class_g_class_ > get();
+ static desc< template_l_class_class_r_class_ > of();
template< template < template < class > class > class T>
- static desc< template_l_template_l_class_g_class_g_class_ > get();
+ static desc< template_l_template_l_class_r_class_r_class_ > of();
template< template < template < class,class > class > class
T>
- static desc< template_l_template_l_class_class_g_class_g_class_ > get();
+ static desc< template_l_template_l_class_class_r_class_r_class_ > of();
// ...
- } // end of namespace mlc::internal::form
+ } // 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)
+/*! \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::internal::wrap<typename mlc::internal::is_a_<
sizeof(mlc::internal::form::get<U >()) >::check<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
Index: mlc/typedef.hh
--- mlc/typedef.hh (revision 387)
+++ mlc/typedef.hh (working copy)
@@ -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 to equip mlc with a static mechanism for a typedef retrieval.
+** 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:
+**
+** #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; \
- } \
+namespace typedef_ { \
+ \
+ namespace internal { \
\
- struct helper_get_typedef__##TypedefName \
+ struct TypedefName \
{ \
typedef char yes; \
struct no { char tmp[2]; }; \
\
- template <typename type, typename alias = typename type::TypedefName> \
+ template <class T, \
+ typename alias = typename T::TypedefName> \
struct run_on; \
\
- template <typename type> \
- static yes selector(run_on<type>*); \
+ template <class T> \
+ static yes selector(run_on<T>*); \
\
- template <typename type> \
+ template <class T> \
static no selector(...); \
\
- template <typename type, bool found> \
+ template <class T, bool found> \
struct result; \
\
- template <typename type> \
- struct result <type, true> \
- { \
- typedef typename type::TypedefName ret; \
+ template <class T> \
+ struct result <T, true> { \
+ typedef typename T::TypedefName ret; \
}; \
\
- template <typename type> \
- struct result <type, false> \
- { \
- typedef mlc::internal::not_found ret; \
- }; \
+ template <class T> \
+ struct result <T, false> { \
+ typedef mlc::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> \
+ } \
+ \
+ struct TypedefName \
+ { \
+ template <class T> \
+ struct in_ \
{ \
- typedef typename get_typedef__##TypedefName <type> ::ret ret; \
+ private: \
+ typedef internal::TypedefName helper_; \
+ enum { \
+ found_ = \
+ (sizeof(helper_::selector<T>(0)) == 1) \
+ }; \
+ public: \
+ typedef \
+ typename helper_::result<T, found_>::ret \
+ ret; \
}; \
\
+ template <class T, bool b> \
+ struct in_onlyif_; \
\
- template <typename type, bool cond> \
- struct helper_get_typedef_onlyif__##TypedefName; \
\
- template <typename type> \
- struct helper_get_typedef_onlyif__##TypedefName <type, false> \
+ template <class T> \
+ struct in_onlyif_ <T, true> \
{ \
- typedef mlc::internal::not_ok ret; \
+ typedef typename in_<T>::ret ret; \
}; \
\
- template <typename type> \
- struct helper_get_typedef_onlyif__##TypedefName <type, true> \
+ template <class T> \
+ struct in_onlyif_ <T, false> \
{ \
- typedef typename type::TypedefName ret; \
+ typedef mlc::dummy 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; \
+ private: \
+ TypedefName() {} \
}; \
\
- template <typename type, typename cond> \
- struct get_typedef_onlyif <type, typedef_::TypedefName, cond> \
- { \
- typedef typename get_typedef_onlyif__##TypedefName <type, cond> ::ret ret; \
- }; \
- \
- \
} \
+ \
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
+/*! \macro mlc_typedef(Type, TypedefName)
+**
+** FIXME: doc
+*/
-// FIXME: mlc should be equipped for typedef retrieval
-// FIXME: and should provide at least facilities for 'ret'
-
-// namespace mlc
-// {
-// mlc_equip_namespace_with_typedef();
-// mlc_decl_typedef(ret);
-// } // end of namespace mlc
-
-
-
-
-// sample code to understand why mlc_typedef_onlyif_of is required
-// in particular situations:
-
-// #include <mlc/typedef.hh>
-
-// mlc_equip_namespace_with_typedef();
-// mlc_decl_typedef(ret);
-
-// struct toto
-// {
-// typedef float does_not_exist;
-// };
-
-// template <class T>
-// struct ok
-// {
-// typedef double ret;
-// typedef typename T::does_not_exist err;
-// };
-
-// template <class T>
-// struct ko
-// {
-// };
-
-// template <class T>
-// void foo()
-// {
-// typedef mlc_typedef_of(T, ret) type;
-// }
+#define mlc_typedef(Type, TypedefName) \
+ typename typedef_::TypedefName::in_<Type>::ret
-// template <class T, class B>
-// void bar()
-// {
-// typedef mlc_typedef_onlyif_of(T, ret, B) type;
-// }
+#define mlc_typedef_(Type, TypedefName) \
+ typedef_::TypedefName::in_<Type>::ret
-// int main()
-// {
-// // code that does not compile:
-// // foo< ok<int> >();
-// // bar< ok<int>, mlc::true_type >();
-// // code that works:
-// foo< ok<toto> >();
-// bar< ok<toto>, mlc::true_type >();
-// bar< ok<int>, mlc::false_type >();
-// }
-/*! \macro mlc_typedef_of( FromType, TypedefName )
+/*! \macro mlc_typedef_onlyif(Type, TypedefName, Bexpr)
**
-** FIXME
-** Sample use: mlc_typedef_of(std::vector<int>, value_type)
+** FIXME: doc
*/
-# define mlc_typedef_of_(FromType, TypedefName) \
-internal::get_typedef__##TypedefName <FromType>::ret
-
-# define mlc_typedef_of(FromType, TypedefName) \
-typename mlc_typedef_of_(FromType, TypedefName)
-
+#define mlc_typedef_onlyif(Type, TypedefName, Bexpr) \
+ typename typedef_::TypedefName::in_onlyif_<Type, mlc_bool(Bexpr)>::ret
-# define mlc_typedef_onlyif_of_(FromType, TypedefName, Condition) \
-internal::get_typedef_onlyif__##TypedefName <FromType, Condition>::ret
+#define mlc_typedef_onlyif_(Type, TypedefName, Bexpr) \
+ typedef_::TypedefName::in_onlyif_<Type, mlc_bool(Bexpr)>::ret
-# define mlc_typedef_onlyif_of(FromType, TypedefName, Condition) \
-typename mlc_typedef_onlyif_of_(FromType, TypedefName, Condition)