https://svn.lrde.epita.fr/svn/oln/trunk/metalic
Index: ChangeLog
from Thierry Geraud <theo(a)lrde.epita.fr>
Modify slightly the ensure_ and ensure_list_ tools.
* mlc/wrap.hh (wrap): Rename into...
(wrap_): ...this.
* mlc/bool.hh (ensure_item): Rename into...
(ensure_item_): ...this and add a parameter to ease disambiguation.
(ensure_list_): Update.
(documentation): Update.
* mlc/cmp.hh: Update.
bool.hh | 82 ++++++++++++++++++++++++++++++++--------------------------------
cmp.hh | 4 +--
wrap.hh | 8 +++---
3 files changed, 48 insertions(+), 46 deletions(-)
Index: mlc/wrap.hh
--- mlc/wrap.hh (revision 388)
+++ mlc/wrap.hh (working copy)
@@ -31,7 +31,7 @@
namespace mlc
{
- /*! \class mlc::wrap<T>
+ /*! \class mlc::wrap_<T>
**
** This class is a workaround to the problem of implicit typename
** that appears when writting something like:
@@ -41,7 +41,7 @@
** typedef typename outer_struct::inner_struct temp;
** temp::value
** you can write directly:
- ** wrap< typename outer_struct::inner_struct >::value
+ ** wrap_< typename outer_struct::inner_struct >::value
**
** This class is used by the mlc_is_a macro.
**
@@ -50,7 +50,7 @@
*/
template <class T>
- struct wrap : public T
+ struct wrap_ : public T
{
typedef T unwrap;
};
@@ -67,7 +67,7 @@
#include <iostream>
#include <mlc/bool.hh>
-template <class T> struct wrap : public T {};
+template <class T> struct wrap_ : public T {};
namespace my
{
Index: mlc/bool.hh
--- mlc/bool.hh (revision 388)
+++ mlc/bool.hh (working copy)
@@ -149,7 +149,7 @@
};
- /*! \class mlc::internal::ensure_item<i, expr>
+ /*! \class mlc::internal::ensure_item_<i, expr, check>
**
** Internal so do not use it. This class is for use in the
** definition of mlc::ensure_<..>.
@@ -160,8 +160,8 @@
** \see mlc::ensure_<..>
*/
- template <unsigned i, typename expr>
- struct ensure_item
+ template <unsigned i, typename expr, typename check>
+ struct ensure_item_
{
};
@@ -175,7 +175,7 @@
** because it is used in inheritance so a ctor should exist. 2)
** This class provides internal_ensure_ so that it acts like the
** value 'true' in a sequence of 'and'; it thus has no effect when
- ** appearing in an ensure_item.
+ ** appearing in an ensure_item_.
**
** \see mlc::ensure_<..>
*/
@@ -201,31 +201,43 @@
** Boolean expression type. An equivalent version for a variadic
** list of parameters is ensure_list_<expr1,..>
**
- ** Sample uses:
+ ** Sample use:
**
** template <class T>
- ** struct dummy : private ensure_< neq_<T, int> >
+ ** struct foo : private virtual ensure_< neq_<T, int> >
** { ...
** };
** means that T can be any type but int.
**
+ **
+ ** Please avoid the following code:
** template <class T1, class T2>
- ** struct dummy2 : private ensure_< neq_<T1, int> >,
- ** private ensure_< neq_<T2, float> >
+ ** struct bar : private virtual ensure_< neq_<T1, int> >,
+ ** private virtual ensure_< neq_<T2, int> >
** { ...
** };
- ** means that T1 should not be int and that T2 should not be float.
- ** This last example is equivalent to:
+ ** a better replacement is:
** template <class T1, class T2>
- ** struct dummy2 : private ensure_list_< neq_<T1, int>,
- ** neq_<T2, float> >
+ ** struct bar : private virtual ensure_list_< neq_<T1, int>,
+ ** neq_<T2, int> >
** { ...
** };
+ ** see the design notes below for details.
+ **
+ ** Also prefer the use of ensure_list_<expr1, expr2> than the
+ ** equivalent ensure_< and_<expr1, expr2> >. Actually, the former
+ ** provides better error messages since the compiler is able to
+ ** say which expr is not verified, whereas the latter cannot.
+ **
**
** 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.
+ ** This class relies on mlc::internal::ensure_item_ to check that
+ ** the expression is true. 3) When several contrains such as
+ ** "private ensure_<..>" appear through a hierarchy of classes or
+ ** for a given class, the program may not compile because of
+ ** multiple inheritance of the same base class; the solution is to
+ ** systematically write "private virtual ensure_<..>".
**
** \see ensure_list_<expr1,..>
**
@@ -233,7 +245,7 @@
template <typename expr>
struct ensure_ :
- private internal::ensure_item<0, typename expr::internal_ensure_>
+ private virtual internal::ensure_item_<0, expr, typename
expr::internal_ensure_>
{
};
@@ -252,30 +264,20 @@
** parameter has to be a Boolean expression type. To check only a
** single expression, the appropriate tool is ensure_<expr>.
**
- ** Sample uses:
**
- ** template <class T>
- ** struct dummy : private ensure_< neq_<T, int> >
- ** { ...
- ** };
- ** means that T can be any type but int.
+ ** Sample use:
**
** template <class T1, class T2>
- ** struct dummy2 : private ensure_< neq_<T1, int> >,
- ** private ensure_< neq_<T2, int> >
- ** { ...
- ** };
- ** is equivalent to:
- ** template <class T1, class T2>
- ** struct dummy2 : private ensure_list< neq_<T1, int>,
+ ** struct foo : private virtual ensure_list_< neq_<T1, int>,
** neq_<T2, int> >
** { ...
** };
**
** 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
- ** each expression is true.
+ ** This class relies on mlc::internal::ensure_item_ to check that
+ ** each expression is true. 3) using "virtual" allow to encompass
+ ** the multiple base class problem.
**
** \see ensure_<expr>
*/
@@ -290,15 +292,15 @@
typename expr_8 = internal::none_,
typename expr_9 = internal::none_>
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_>,
- private internal::ensure_item<4, typename expr_4::internal_ensure_>,
- private internal::ensure_item<5, typename expr_5::internal_ensure_>,
- private internal::ensure_item<6, typename expr_6::internal_ensure_>,
- private internal::ensure_item<7, typename expr_7::internal_ensure_>,
- private internal::ensure_item<8, typename expr_8::internal_ensure_>,
- private internal::ensure_item<9, typename expr_9::internal_ensure_>
+ private virtual internal::ensure_item_<1, expr_1, typename
expr_1::internal_ensure_>,
+ private virtual internal::ensure_item_<2, expr_2, typename
expr_2::internal_ensure_>,
+ private virtual internal::ensure_item_<3, expr_3, typename
expr_3::internal_ensure_>,
+ private virtual internal::ensure_item_<4, expr_4, typename
expr_4::internal_ensure_>,
+ private virtual internal::ensure_item_<5, expr_5, typename
expr_5::internal_ensure_>,
+ private virtual internal::ensure_item_<6, expr_6, typename
expr_6::internal_ensure_>,
+ private virtual internal::ensure_item_<7, expr_7, typename
expr_7::internal_ensure_>,
+ private virtual internal::ensure_item_<8, expr_8, typename
expr_8::internal_ensure_>,
+ private virtual internal::ensure_item_<9, expr_9, typename
expr_9::internal_ensure_>
{
};
@@ -352,7 +354,7 @@
** (and thus no significant value). A static check via
** "mlc::ensure_<..>" uses this typedef.
**
- ** \see mlc::internal::ensure_item<i, expr>
+ ** \see mlc::internal::ensure_item_<i, expr>
*/
typedef internal::none_ internal_ensure_;
Index: mlc/cmp.hh
--- mlc/cmp.hh (revision 388)
+++ mlc/cmp.hh (working copy)
@@ -56,7 +56,7 @@
/// Equality test between a couple of types.
template <typename T1, typename T2>
- struct eq_ : private ensure_< is_not_value<T1>,
+ struct eq_ : private ensure_list_< is_not_value<T1>,
is_not_value<T2> >,
public false_
{
@@ -72,7 +72,7 @@
/// Inequality test between a couple of types.
template <typename T1, typename T2>
- struct neq_ : private ensure_< is_not_value<T1>,
+ struct neq_ : private ensure_list_< is_not_value<T1>,
is_not_value<T2> >,
public true_
{