This implementation is not generic but shows difficulties with the use
of point and dpoint.
For details, please see the topic in lrde.olena (coming soon :)) about
the arguing of points and dpoints in Olena.
--
Widynski Nicolas
Promo 2007
https://svn/svn/oln/prototypes/proto-1.0/olena
Index: ChangeLog
from Nicolas Widynski <nicolas.widynski(a)lrde.epita.fr>
Implementation of a denoising image processing algorithm : Non Local Means.
* oln/appli/denoising/nl_means.hh: New. NL-means algorithm.
* oln/makefile.src: Update for laplacian convolution and NL-means algorithm.
appli/denoising/nl_means.hh | 141 ++++++++++++++++++++++++++++++++++++++++++++
makefile.src | 4 +
2 files changed, 145 insertions(+)
Index: oln/appli/denoising/nl_means.hh
--- oln/appli/denoising/nl_means.hh (revision 0)
+++ oln/appli/denoising/nl_means.hh (revision 0)
@@ -0,0 +1,141 @@
+// Copyright (C) 2001, 2002, 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 OLENA_DENOISING_NLMEANS_HH
+# define OLENA_DENOISING_NLMEANS_HH
+
+# define SQR(u) u*u
+# define PI 3.141592653589793238462643
+
+# include <cmath>
+# include <oln/level/fill.hh>
+
+namespace oln {
+
+ namespace denoising {
+
+ namespace impl {
+
+
+ template<typename I>
+ const oln_type_of(I, concrete) gaussian_mask(double variance,
+ int rows,
+ int cols)
+ {
+ oln_type_of(I, concrete) g_m(rows, cols, 0);
+
+ int i, j;
+
+ for (i = 0; i < rows; i++)
+ for (j = 0; j < cols; j++)
+ g_m(i,j) = (1 / 2 * PI * SQR(variance)) * exp(-(SQR(rows / 2 - i) + SQR(cols / 2 - j)));
+
+ return g_m;
+ }
+
+
+ template<typename I>
+ oln_type_of(I, concrete) nl_means_(const oln::abstract::image<I>& input,
+ int window,
+ double variance,
+ int horizon)
+ {
+ oln_type_of(I, concrete) nl(input.size(), "nl_means");
+ oln_type_of(I, concrete) g_m;
+ oln_type_of(I, fwd_piter) p(input.size());
+ oln_type_of(I, point) pt1;
+ oln_type_of(I, point) pt2;
+
+ int i, j, k, l, i2, j2, k2, l2;
+ double dist;
+ double w;
+ double Z;
+ double val;
+
+
+ level::fill(nl, 0);
+
+ g_m = gaussian_mask<I>(variance, window, window);
+
+ for (i = 0; i < input.size().ncols(); i++)
+ {
+ for (j = 0; j < input.size().nrows(); j++)
+ {
+ Z = 0;
+ val = 0;
+
+ for (k = i - horizon; k < i + horizon; k++)
+ for (l = j - horizon; l < j + horizon; l++)
+ {
+ if (not (k >= 0 and k < (int)input.size().ncols() and l >= 0 and l < (int)input.size().nrows()))
+ continue;
+
+ dist = 0;
+ w = 0;
+
+ for (k2 = k - window / 2, i2 = i - window / 2; k2 < (k + window / 2 + window % 2); k2++, i2++)
+ for (l2 = l - window / 2, j2 = j - window / 2; l2 < (l + window / 2 + window % 2); l2++, j2++)
+
+ if (i2 >= 0 and i2 < input.size().ncols() && j2 >= 0 and j2 < input.size().nrows() and
+ k2 >= 0 and k2 < input.size().ncols() && l2 >= 0 and l2 < input.size().nrows())
+ {
+ dist += g_m.exact()(k2 + window / 2 - k, l2 + window / 2 - l) *
+ ((input.exact()(i2, j2) - input.exact()(k2, l2)) *
+ (input.exact()(i2, j2) - input.exact()(k2, l2)));
+ }
+
+ w = exp(-dist/(SQR(variance)));
+ val += w * input.exact()(k, l).value();
+ Z += w;
+ }
+
+ nl(i,j) = val / Z;
+ }
+
+ std::cout << (int)input.size().nrows() << " / " << i + 1 << std::endl;
+ }
+
+ return nl;
+ }
+
+ } // end of namespace oln::denoising::impl
+
+ template<typename I>
+ oln_type_of(I, concrete) nl_means(const oln::abstract::image<I>& input,
+ int window,
+ double variance,
+ int horizon)
+ {
+ return impl::nl_means_(input.exact(), window, variance, horizon);
+ }
+
+
+ } // end of namespace oln::denoising
+
+} // end of namespace oln
+
+#endif // OLENA_DENOISING_NLMEANS_HH
Index: oln/makefile.src
--- oln/makefile.src (revision 390)
+++ oln/makefile.src (working copy)
@@ -10,6 +10,8 @@
appli/astro/tree_coherence_check.hh \
appli/astro/tree_statistics.hh \
\
+ appli/denoising/nl_means.hh \
+ \
basics1d.hh \
basics2d.hh \
basics3d.hh \
@@ -30,6 +32,8 @@
convert/stretch.hh \
convert/value_to_point.hh \
\
+ convolution/laplacian.hh \
+ \
core/1d/array1d.hh \
core/1d/bkd_piter1d.hh \
core/1d/dpoint1d.hh \
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_
{
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)
https://svn.lrde.epita.fr/svn/oln/trunk/metalic
Index: ChangeLog
from Thierry Geraud <theo(a)lrde.epita.fr>
Add mlc::ensure_ and update. .
* mlc/bool.hh: Update documentation.
(internal::value_<bool,b>::ret): Rename as...
(internal::value_<bool,b>::eval): ...this.
(bool_<true>::ensure_t): Rename as...
(bool_<true>::internal_ensure_): ...this.
(internal::ensure_item<i,expr>): New class.
(internal::none_): Relocate.
(internal::none_::internal_ensure_): New typedef.
(ensure_): New class.
* mlc/value.hh (is_value, is_not_value): Move to...
* mlc/cmp.hh (is_value, is_not_value): ...here.
(eq_, neq_): Update static checks.
bool.hh | 170
+++++++++++++++++++++++++++++++++++++++++++++------------------
cmp.hh | 22 ++++++--
value.hh | 25 +++++----
3 files changed, 156 insertions(+), 61 deletions(-)
Index: mlc/bool.hh
--- mlc/bool.hh (revision 385)
+++ mlc/bool.hh (working copy)
@@ -115,7 +115,7 @@
*/
static const bool value = b;
- /*! \typedef ret
+ /*! \typedef eval
**
** Returns mlc::true_ or mlc::false_.
**
@@ -127,11 +127,13 @@
** Please note that, however, we usually do not need expression
** evaluation. The most common use of a Boolean expression is
** to check that it is verified (true) and, for that, we provide
- ** ::ensure() and ::ensure_t.
+ ** "expr::ensure();" and "ensure_<expr..>". For instance:
+ ** or_<mlc_is_a(T, int), mlc_is_a(T, unsigned)>::ensure();
+ ** ensures that T is int or unsigned without using ::eval.
**
- ** \see mlc::true_ and mlc::false_
+ ** \see mlc::true_, mlc::false_, mlc::ensure_<expr..>.
*/
- typedef bool_<b> ret;
+ typedef bool_<b> eval;
private:
@@ -146,9 +148,112 @@
template <typename T> friend class get_bool;
};
+
+ /*! \class mlc::internal::ensure_item<i, expr>
+ **
+ ** Internal so do not use it. This class is for use in the
+ ** definition of mlc::ensure_<..>.
+ **
+ ** Design note: this class does not derive from abstract::type
+ ** because it is used in inheritance so a ctor should exist.
+ **
+ ** \see mlc::ensure_<..>
+ */
+
+ template <unsigned i, typename expr>
+ struct ensure_item
+ {
+ };
+
+
+ /*! \class mlc::internal::none_
+ **
+ ** Internal so do not use it. This class is for use in the
+ ** definition of mlc::ensure_<..>.
+ **
+ ** 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 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.
+ **
+ ** \see mlc::ensure_<..>
+ */
+
+ struct none_
+ {
+ typedef none_ internal_ensure_; // provided such as in classes
inheriting from true_
+ };
+
+
} // end of namespace mlc::internal
+
+ /*! \class mlc::ensure_<expr1..>
+ **
+ ** This class is a replacement for a sequence of instructions:
+ ** "expr1::ensure(); .." when there is no room for having
+ ** instructions. The typical use is to express a constraint (or
+ ** 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.
+ **
+ ** 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, int> >
+ ** { ...
+ ** };
+ ** is equivalent to:
+ ** template <class T1, class T2>
+ ** struct dummy2 : private ensure_< 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.
+ **
+ */
+
+ template <typename expr_1,
+ typename expr_2 = internal::none_,
+ typename expr_3 = internal::none_,
+ typename expr_4 = internal::none_,
+ typename expr_5 = internal::none_,
+ typename expr_6 = internal::none_,
+ typename expr_7 = internal::none_,
+ typename expr_8 = internal::none_,
+ typename expr_9 = internal::none_>
+ struct ensure_ :
+ 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_>
+ {
+ };
+
+
+
+
/*! \class mlc::bool_<true>
**
** Specialization of mlc::bool_<b> for b set to true. This type
@@ -177,55 +282,29 @@
** "Expr::ensure();"
**
** When there is no room in code for an instruction, use
- ** ensure_t instead.
+ ** mlc::ensure_<expr1..> instead.
**
** Design note: This member is a no-op (it has no cost at
** run-time).
+ **
+ ** \see: mlc::ensure<expr1..>
*/
static void ensure() {}
- /*! \typedef ensure_t
- **
- ** This typedef is inherited in every Boolean expression types that
- ** derive from mlc::true_. This typedef is not provided in
- ** mlc::false_. The type returned by this typedef has no meaning
- ** (and thus no significant value).
+ /*! \typedef internal_ensure_
**
- ** A static check to ensure that a Boolean expression type, say
- ** Expr, is verified can thus be written through the typedef
- ** access: "Expr::ensure_t". This is a replacement for the
- ** instruction "Expr::ensure();" when there is no room in code for
- ** an instruction.
+ ** This is internal stuff so do not use it.
**
- ** Sample use:
- ** template <class T>
- ** struct foo
- ** : private mlc_is_a(T, base)::ensure_t
- ** {
- ** //...
- ** };
- ** meaning that foo's parameter is constrainted to be a sub-class
- ** of base.
+ ** This typedef is inherited in every Boolean expression types
+ ** that derive from mlc::true_. This typedef is not provided in
+ ** mlc::false_. The type returned by this typedef has no meaning
+ ** (and thus no significant value). A static check via
+ ** "mlc::ensure_<..>" uses this typedef.
**
- ** Limitation: when using ensure_t to express several
- ** constraints through private inheritance, such as in the sample
- ** use above, one should express the set of constraints by a
- ** single expression. The following code is not ok:
- ** template <class T1, class T2>
- ** struct foo
- ** : private mlc_is_a(T1, base)::ensure_t,
- ** private mlc_is_a(T2, base)::ensure_t
- ** { ... };
- ** the problem being that we mulitply inherit from the same
- ** class. The correct code should be written with a single
- ** Boolean; practically the following code is ok:
- ** template <class T1, class T2>
- ** struct foo
- ** : private mlc::and_<mlc_is_a(T1, base),
- ** mlc_is_a(T2, base)>::ensure_t
- ** { ... };
+ ** \see mlc::internal::ensure_item<i, expr>
*/
- typedef struct{} ensure_t;
+ typedef internal::none_ internal_ensure_;
+
};
typedef bool_<true> true_;
@@ -238,9 +317,9 @@
** derive either from this type or from mlc::true_.
**
** Conversely to mlc::true_, this class does not feature ensure()
- ** nor ensure_t. So, when a Boolean expression type, say Expr,
+ ** nor ensure_. So, when a Boolean expression type, say Expr,
** is evaluated to false, the static checks "Expr::ensure();" and
- ** "Expr::ensure_t" do not compile.
+ ** "Expr::ensure_" do not compile.
**
** Design notes: 1) This specialization is defined so that mlc
** Booleans derive from mlc::abstract::boolean. 2) This
@@ -321,7 +400,6 @@
namespace internal
{
- struct none_;
// ors_2_
template <typename A1, typename A2> struct ors_2_ :
public or_<A1, A2> {};
Index: mlc/value.hh
--- mlc/value.hh (revision 385)
+++ mlc/value.hh (working copy)
@@ -162,22 +162,25 @@
# include <mlc/bool.hh>
-# include <mlc/is_a.hh>
-namespace mlc {
+// FIXME: the following code causes inclusion recursion...
- template <typename T>
- struct is_value : public mlc_is_a(T, mlc::abstract::value)
- {
- };
+// # include <mlc/is_a.hh>
- template <typename T>
- struct is_not_value : public not_<mlc_is_a(T, mlc::abstract::value)>
- {
- };
+// namespace mlc {
-} // end of 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 385)
+++ mlc/cmp.hh (working copy)
@@ -39,18 +39,31 @@
namespace mlc
{
+ // FIXME: code moved from the end of value.hh
+
+ 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)>
+ {
+ };
+
/// Equality test between a couple of types.
template <typename T1, typename T2>
- struct eq_ : private and_< is_not_value<T1>, is_not_value<T2>
>::ensure_type,
+ struct eq_ : private ensure_< is_not_value<T1>,
+ is_not_value<T2> >,
public false_
{
};
template <typename T>
- struct eq_ <T, T> : private is_not_value<T>::ensure_type,
+ struct eq_ <T, T> : private ensure_< is_not_value<T> >,
public true_
{
};
@@ -59,13 +72,14 @@
/// Inequality test between a couple of types.
template <typename T1, typename T2>
- struct neq_ : private and_< is_not_value<T1>, is_not_value<T2>
>::ensure_type,
+ struct neq_ : private ensure_< is_not_value<T1>,
+ is_not_value<T2> >,
public true_
{
};
template <typename T>
- struct neq_ <T, T> : private is_not_value<T>::ensure_type,
+ struct neq_ <T, T> : private ensure_< is_not_value<T> >,
public false_
{
};
https://svn.lrde.epita.fr/svn/oln/trunk
Index: ChangeLog
from Thierry Geraud <theo(a)lrde.epita.fr>
Clean up of core mlc classes and add some documentation.
A lot of cleanups. Client concrete classes in mlc are now all
postfixed by '_'. For instance, we have and_, int_, and so on.
* metalic: New.
* metalic/mlc: New.
* metalic/mlc/type.hh: New.
* metalic/mlc/bool.hh: New.
(abstract::boolean): New class.
(bool_): New class.
(value, true_type, false_type): Rename as...
(value_, true_, false_): ...these.
(ors, ands): Rename as...
(ors_, ands_): ...these.
(internal): Cosmetic change.
(is_true, is_false): Remove.
(true_, false_): New typedef ensure_t.
* metalic/mlc/is_a.hh: New.
(form): Move in the internal namespace cause names are too long
for a decent client use.
* metalic/mlc/value.hh: New.
(value): Rename as...
(value_): ...this.
(mlc_internal_decl_unsigned_): New macro.
(mlc_internal_decl_signed_): New macro.
(uchar_, ushort_, uint_, ulong_): New classes.
(schar_, short_, int_, long_): New classes.
(is_value, is_not_value): New meta-functions.
* metalic/mlc/flags.hh: New.
(flag): New abstract class.
(undefined_type, unknown_type, no_type): Rename as...
(undefined, unknown, none): ...these.
(not_ok): Remove cause useless.
* metalic/mlc/cmp.hh: New.
(eq, neq): Rename as...
(eq_, neq_): ...these.
(is_found, is_not_found, is_ok): Remove cause irrelevant here.
(mlc_is_found, mlc_is_not_found): Likewise.
* metalic/mlc/typedef.hh: New.
bool.hh | 417 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
cmp.hh | 46 ++----
flags.hh | 83 +++++++++---
is_a.hh | 67 ++++------
type.hh | 61 +++++++++
value.hh | 154 +++++++++++++++++++++--
6 files changed, 624 insertions(+), 204 deletions(-)
Index: metalic/mlc/type.hh
--- metalic/mlc/type.hh (revision 0)
+++ metalic/mlc/type.hh (revision 0)
@@ -0,0 +1,61 @@
+// Copyright (C) 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_TYPE_HH
+# define METALIC_TYPE_HH
+
+
+namespace mlc {
+
+ namespace abstract {
+
+ /*! \class mlc::abstract::type
+ **
+ ** Abstract base class for about all the types defined in the mlc
+ ** library. Types deriving from this class are intended to be
+ ** used only as types, not as objects; so they cannot be
+ ** instantiated.
+ **
+ ** This class is useful to check at compile-time that a parameter
+ ** P is an mlc type (with the "mlc_is_a" facility).
+ **
+ ** Example: mlc::true_ is a mlc::abstract::type.
+ */
+
+ struct type
+ {
+ private:
+ /// Ctor is private to prevent instantiations.
+ type() {}
+ };
+
+ } // end of namespace mlc::abstract
+
+} // end of namespace mlc
+
+
+#endif // ! METALIC_TYPE_HH
Index: metalic/mlc/bool.hh
--- metalic/mlc/bool.hh (revision 0)
+++ metalic/mlc/bool.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2001, 2002, 2003, 2004, 2005 EPITA Research and Development Laboratory
+// 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
@@ -29,166 +29,385 @@
# define METALIC_BOOL_HH
# include <mlc/value.hh>
-# include <mlc/types.hh>
-/// Macro that retrieves a Boolean value from a static type representing a Boolean.
-# define mlc_bool(Type) mlc::internal::helper_get_bool< Type >::ret
+/*! \macro mlc_bool(T)
+**
+** Macro that retrieves a Boolean value from a Boolean expression type
+** T. Its result is either true or false.
+*/
+# define mlc_bool(Type) mlc::internal::get_bool<Type>::value
namespace mlc
{
- /// Specializations of mlc::value for T = bool; when v = true, ensure() is provided.
+ namespace abstract {
- template <>
- struct value <bool, true>
- {
- static const bool Boolean_value = true;
- static const bool val = true;
- static void ensure() {}
- protected:
- value() {}
- };
+ /*! \class mlc::abstract::boolean
+ **
+ ** Abstract base class for Booleans represented as types. This
+ ** class has two important sub-classes: mlc::true_ and
+ ** mlc::false_.
+ **
+ ** Any mlc Boolean expression type derives from either mlc::true_
+ ** or mlc::false_ so derives from mlc::abstract::boolean.
+ */
- template <>
- struct value <bool, false>
- {
- static const bool Boolean_value = false;
- static const bool val = false;
- protected:
- value() {}
- };
+ struct boolean : public value {};
+
+ } // end of mlc::abstract
- /// Typedefs of true_type and false_type.
- typedef value<bool, true> true_type;
- typedef value<bool, false> false_type;
+ // fwd decl
+ template <bool> struct bool_;
namespace internal
{
+ /*! \class mlc::get_bool<T>
+ **
+ ** Internal class so do not use it. This class gives access to a
+ ** Boolean value from a Boolean expression type; it is used in the
+ ** mlc_bool(T) macro.
+ **
+ ** \see mlc_bool(T)
+ */
template <typename T>
- struct helper_get_bool
+ struct get_bool
{
- // FIXME: static check that T dderives from either true_type or false_type...
- static const bool ret = T::Boolean_value;
+ static const bool value = T::bool_value_;
};
- } // end of namespace mlc::internal
-
-
- /// Classes is_true<b> and is_false<b> (only provided for bkd compability).
+ /*! \class mlc::value_<bool, b>
+ **
+ ** Specialization of value_<T, val> for the Boolean case.
+ **
+ ** Design notes: 1) This specialization is defined so that mlc
+ ** Booleans derive from mlc::abstract::boolean. 2) This
+ ** specialization conforms to the interface of the generic version
+ ** of mlc::internal::value_.
+ */
- template <bool b> struct is_true {};
- template <> struct is_true <true> { static void ensure() {} };
+ template <bool b>
+ struct value_ <bool, b> : public abstract::boolean
+ {
+ /*! \typedef type
+ **
+ ** Gives the regular type, that is bool, corresponding to this
+ ** class.
+ */
+ typedef bool type;
+
+ /*! \member value
+ **
+ ** Gives the regular value of the Boolean represented by this
+ ** class. The result is either true or false.
+ **
+ ** This member is provided for any mlc value class such as
+ ** mlc::int_<51> and mlc::char_<'c'>. However, to access the
+ ** regular value of a type T that you know to be a mlc Boolean
+ ** expression, you should prefer to use the macro mlc_bool(T).
+ ** This macro also ensures that T really is an expression.
+ **
+ */
+ static const bool value = b;
+
+ /*! \typedef ret
+ **
+ ** Returns mlc::true_ or mlc::false_.
+ **
+ ** Since Boolean expression types derive from either mlc::true_
+ ** or mlc::false_, these expression types are never exactly
+ ** mlc::true_ nor mlc::false_. This typedef thus allows for the
+ ** expression evaluation.
+ **
+ ** Please note that, however, we usually do not need expression
+ ** evaluation. The most common use of a Boolean expression is
+ ** to check that it is verified (true) and, for that, we provide
+ ** ::ensure() and ::ensure_t.
+ **
+ ** \see mlc::true_ and mlc::false_
+ */
+ typedef bool_<b> ret;
+
+ private:
+
+ /*! \member bool_value_
+ **
+ ** This member is redundant with the member 'value'. It is used
+ ** by the mlc_bool(T) macro to ensure that T actually derives
+ ** from mlc::true_ or mlc::false_.
+ */
+ static const bool bool_value_ = b;
- template <bool b> struct is_false {};
- template <> struct is_false <false> { static void ensure() {} };
+ template <typename T> friend class get_bool;
+ };
+ } // end of namespace mlc::internal
- /// Logical unary not of a Boolean type
+ /*! \class mlc::bool_<true>
+ **
+ ** Specialization of mlc::bool_<b> for b set to true. This type
+ ** is also known as mlc::true_. Every Boolean expression types
+ ** derive either from this type or from mlc::false_.
+ **
+ ** Design notes: 1) This specialization is defined so that mlc
+ ** Booleans derive from mlc::abstract::boolean. 2) This
+ ** specialization conforms to the interface of the generic version
+ ** of mlc::internal::value_.
+ **
+ ** \see mlc::bool_<false>
+ */
- template <typename T>
- struct not_ : public value<bool, !mlc_bool(T)>
+ template <>
+ struct bool_<true> : public internal::value_<bool, true>
{
- // FIXME: static assert here and below s.a. ~not_() { mlc_is_a(not_<T>, Boolean_value); }
- };
+ /*! \member ensure()
+ **
+ ** This member is inherited in every Boolean expression types that
+ ** derive from mlc::true_. This member is not provided in
+ ** mlc::false_.
+ **
+ ** A static check to ensure that a Boolean expression type, say
+ ** Expr, is verified can thus be written as an instruction:
+ ** "Expr::ensure();"
+ **
+ ** When there is no room in code for an instruction, use
+ ** ensure_t instead.
+ **
+ ** Design note: This member is a no-op (it has no cost at
+ ** run-time).
+ */
+ static void ensure() {}
- /// Logical binary operators between a couple of Boolean types
+ /*! \typedef ensure_t
+ **
+ ** This typedef is inherited in every Boolean expression types that
+ ** derive from mlc::true_. This typedef is not provided in
+ ** mlc::false_. The type returned by this typedef has no meaning
+ ** (and thus no significant value).
+ **
+ ** A static check to ensure that a Boolean expression type, say
+ ** Expr, is verified can thus be written through the typedef
+ ** access: "Expr::ensure_t". This is a replacement for the
+ ** instruction "Expr::ensure();" when there is no room in code for
+ ** an instruction.
+ **
+ ** Sample use:
+ ** template <class T>
+ ** struct foo
+ ** : private mlc_is_a(T, base)::ensure_t
+ ** {
+ ** //...
+ ** };
+ ** meaning that foo's parameter is constrainted to be a sub-class
+ ** of base.
+ **
+ ** Limitation: when using ensure_t to express several
+ ** constraints through private inheritance, such as in the sample
+ ** use above, one should express the set of constraints by a
+ ** single expression. The following code is not ok:
+ ** template <class T1, class T2>
+ ** struct foo
+ ** : private mlc_is_a(T1, base)::ensure_t,
+ ** private mlc_is_a(T2, base)::ensure_t
+ ** { ... };
+ ** the problem being that we mulitply inherit from the same
+ ** class. The correct code should be written with a single
+ ** Boolean; practically the following code is ok:
+ ** template <class T1, class T2>
+ ** struct foo
+ ** : private mlc::and_<mlc_is_a(T1, base),
+ ** mlc_is_a(T2, base)>::ensure_t
+ ** { ... };
+ */
+ typedef struct{} ensure_t;
+ };
- template <typename L, typename R> struct and_ : public value <bool, (mlc_bool(L) && mlc_bool(R)) > {};
- template <typename L, typename R> struct nand_ : public value <bool, (!(mlc_bool(L) && mlc_bool(R)))> {};
- template <typename L, typename R> struct or_ : public value <bool, (mlc_bool(L) || mlc_bool(R)) > {};
- template <typename L, typename R> struct nor_ : public value <bool, (!(mlc_bool(L) || mlc_bool(R)))> {};
- template <typename L, typename R> struct xor_ : public value <bool, (mlc_bool(L) != mlc_bool(R)) > {};
- template <typename L, typename R> struct xnor_ : public value <bool, (!(mlc_bool(L) != mlc_bool(R)))> {};
+ typedef bool_<true> true_;
+ /*! \class mlc::bool_<false>
+ **
+ ** Specialization of mlc::bool_<b> for b set to false. This type
+ ** is also known as mlc::false_. Every Boolean expression types
+ ** derive either from this type or from mlc::true_.
+ **
+ ** Conversely to mlc::true_, this class does not feature ensure()
+ ** nor ensure_t. So, when a Boolean expression type, say Expr,
+ ** is evaluated to false, the static checks "Expr::ensure();" and
+ ** "Expr::ensure_t" do not compile.
+ **
+ ** Design notes: 1) This specialization is defined so that mlc
+ ** Booleans derive from mlc::abstract::boolean. 2) This
+ ** specialization conforms to the interface of the generic version
+ ** of mlc::internal::value_.
+ **
+ ** \see mlc::bool_<true>
+ */
- namespace internal
+ template <>
+ struct bool_<false> : public internal::value_<bool, false>
{
- // helpers for mlc::ors
+ };
- template <typename A1, typename A2>
- struct ors2 : public or_<A1, A2> {};
+ typedef bool_<false> false_;
+
+
+ /*! \class mlc::not_<T>
+ **
+ ** Logical unary 'not' operator on a Boolean expression type. This
+ ** class is also a Boolean expression type.
+ */
+ template <typename T> struct not_ : public bool_<(!mlc_bool(T))> {};
+
+
+ /*! \class mlc::and_<L,R>
+ **
+ ** Logical binary 'and' operator on a couple of Boolean expression
+ ** types. This class is also a Boolean expression type.
+ **
+ ** \see mlc::ands_<..>
+ */
+ template <typename L, typename R> struct and_ : public bool_< (mlc_bool(L) && mlc_bool(R)) > {};
+
+ /*! \class mlc::nand_<L,R>
+ **
+ ** Logical binary 'not and' operator on a couple of Boolean
+ ** expression types. This class is also a Boolean expression type.
+ **
+ ** Design note: an equivalent is mlc::not_< mlc::and_<L,R> >.
+ */
+ template <typename L, typename R> struct nand_ : public bool_<(!(mlc_bool(L) && mlc_bool(R)))> {};
+
+ /*! \class mlc::or_<L,R>
+ **
+ ** Logical binary 'or' operator on a couple of Boolean expression
+ ** types. This class is also a Boolean expression type.
+ **
+ ** \see mlc::ors_<..>
+ */
+ template <typename L, typename R> struct or_ : public bool_< (mlc_bool(L) || mlc_bool(R)) > {};
+
+ /*! \class mlc::nor_<L,R>
+ **
+ ** Logical binary 'not or' operator on a couple of Boolean
+ ** expression types. This class is also a Boolean expression type.
+ **
+ ** Design note: an equivalent is mlc::not_< mlc::or_<L,R> >.
+ */
+ template <typename L, typename R> struct nor_ : public bool_<(!(mlc_bool(L) || mlc_bool(R)))> {};
+
+ /*! \class mlc::xor_<L,R>
+ **
+ ** Logical binary 'exclusive or' operator on a couple of Boolean
+ ** expression types. This class is also a Boolean expression type.
+ */
+ template <typename L, typename R> struct xor_ : public bool_< (mlc_bool(L) != mlc_bool(R)) > {};
+
+ /*! \class mlc::xnor_<L,R>
+ **
+ ** Logical binary 'exclusive not or' operator on a couple of Boolean
+ ** expression types. This class is also a Boolean expression type.
+ */
+ template <typename L, typename R> struct xnor_ : public bool_<(!(mlc_bool(L) != mlc_bool(R)))> {};
- template <>
- struct ors2 <no_type, no_type> : public true_type {};
- template <typename A1>
- struct ors2 <A1, no_type> : public A1 {};
+ /// Internal helpers for logical operators between several Boolean types
- template <typename A2>
- struct ors2 <no_type, A2>;
+ namespace internal
+ {
+ struct none_;
+ // ors_2_
+ template <typename A1, typename A2> struct ors_2_ : public or_<A1, A2> {};
+ template <> struct ors_2_ <none_, none_> : public true_ {};
+ template <typename A1> struct ors_2_ <A1, none_> : public A1 {};
+ template <typename A2> struct ors_2_ <none_, A2>;
+ // ors_4_
template <typename A1, typename A2,
typename A3, typename A4>
- struct ors4 : public ors2< ors2<A1, A2>, ors2<A3, A4> > {};
-
+ struct ors_4_ : public ors_2_< ors_2_<A1, A2>,
+ ors_2_<A3, A4> > {};
template <>
- struct ors4 <no_type, no_type, no_type, no_type> : public true_type {};
-
+ struct ors_4_ <none_, none_, none_, none_> : public true_ {};
+ // ors_8_
template <typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7, typename A8>
- struct ors8 : public ors2< ors4<A1, A2, A3, A4>, ors4<A5, A6, A7, A8> > {};
-
- // helpers for mlc::ands
-
- template <typename A1, typename A2>
- struct ands2 : public and_<A1, A2> {};
-
- template <>
- struct ands2 <no_type, no_type> : public true_type {};
-
- template <typename A1>
- struct ands2 <A1, no_type> : public A1 {};
-
- template <typename A2>
- struct ands2 <no_type, A2>;
-
+ struct ors_8_ : public ors_2_< ors_4_<A1, A2, A3, A4>,
+ ors_4_<A5, A6, A7, A8> > {};
+ // ands_2_
+ template <typename A1, typename A2> struct ands_2_ : public and_<A1, A2> {};
+ template <> struct ands_2_ <none_, none_> : public true_ {};
+ template <typename A1> struct ands_2_ <A1, none_> : public A1 {};
+ template <typename A2> struct ands_2_ <none_, A2>;
+ // ands_4_
template <typename A1, typename A2,
typename A3, typename A4>
- struct ands4 : public ands2< ands2<A1, A2>, ands2<A3, A4> > {};
-
+ struct ands_4_ : public ands_2_< ands_2_<A1, A2>,
+ ands_2_<A3, A4> > {};
template <>
- struct ands4 <no_type, no_type, no_type, no_type> : public true_type {};
-
+ struct ands_4_ <none_, none_, none_, none_> : public true_ {};
+ // ands_8_
template <typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7, typename A8>
- struct ands8 : public ands2< ands4<A1, A2, A3, A4>, ands4<A5, A6, A7, A8> > {};
+ struct ands_8_ : public ands_2_< ands_4_<A1, A2, A3, A4>,
+ ands_4_<A5, A6, A7, A8> > {};
} // end of mlc::internal
- // 'ors' is a list of 'or_'.
+ /*! \class mlc::ors_<..>
+ **
+ ** Logical n-ary 'or' operator on a set of Boolean expression types.
+ ** The number of arguments (parameters) should be at least 3 and at
+ ** most 8. This class is also a Boolean expression type.
+ **
+ ** Sample use:
+ ** mlc::ors_< mlc::eq_<T, int>,
+ ** mlc_is_a(T, mlc::int_),
+ ** mlc_is_a(T, my::integer) >
+ **
+ ** \see mlc::or_<L,R> mlc::ands_<..>
+ */
template <typename A1,
typename A2,
typename A3,
- typename A4 = no_type,
- typename A5 = no_type,
- typename A6 = no_type,
- typename A7 = no_type,
- typename A8 = no_type>
- struct ors : public internal::ors8< A1, A2, A3, A4, A5, A6, A7, A8 >
- {};
+ typename A4 = internal::none_,
+ typename A5 = internal::none_,
+ typename A6 = internal::none_,
+ typename A7 = internal::none_,
+ typename A8 = internal::none_>
+ struct ors_ : public internal::ors_8_< A1, A2, A3, A4, A5, A6, A7, A8 >
+ {
+ };
+
- // 'ands' is a list of 'and_'.
+ /*! \class mlc::ands_<..>
+ **
+ ** Logical n-ary 'and' operator on a set of Boolean expression types.
+ ** The number of arguments (parameters) should be at least 3 and at
+ ** most 8. This class is also a Boolean expression type.
+ **
+ ** \see mlc::and_<L,R> mlc::ors_<..>
+ */
template <typename A1,
typename A2,
typename A3,
- typename A4 = no_type,
- typename A5 = no_type,
- typename A6 = no_type,
- typename A7 = no_type,
- typename A8 = no_type>
- struct ands : public internal::ands8< A1, A2, A3, A4, A5, A6, A7, A8 >
- {};
+ typename A4 = internal::none_,
+ typename A5 = internal::none_,
+ typename A6 = internal::none_,
+ typename A7 = internal::none_,
+ typename A8 = internal::none_>
+ struct ands_ : public internal::ands_8_< A1, A2, A3, A4, A5, A6, A7, A8 >
+ {
+ };
} // end of namespace mlc
Index: metalic/mlc/is_a.hh
--- metalic/mlc/is_a.hh (revision 0)
+++ metalic/mlc/is_a.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2001, 2002, 2003, 2004, 2005 EPITA Research and Development Laboratory
+// 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
@@ -28,13 +28,13 @@
#ifndef METALIC_IS_A_HH
# define METALIC_IS_A_HH
-# include <mlc/any.hh>
# include <mlc/bool.hh>
-// private macro so do _not_ use it
-# define is_a__check_result_ \
-sizeof(helper<T ,U >::check( (T *) helper<T,U >::makeT() )) \
-== sizeof(mlc::internal::yes_)
+
+
+// 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_)
namespace mlc
@@ -44,23 +44,13 @@
{
//
- // wrap
- //
- // FIXME: This type is a workaround for g++-2.95 problem with implicit
- // typename in <foo<T>::ret::dim>,
- // write <wrap<typename foo<T>::ret>::dim instead.
- //
-
+ // 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 {};
- } // internal
-
- /*-----.
- | is_a |
- `-----*/
- // FIXME: form is a namespace to avoid g++-3.2 bug with template function
- // overloading in class.
+ /// form
namespace form
{
@@ -93,10 +83,9 @@
static desc< template_l_template_l_class_class_g_class_g_class_ > get();
// ...
- }
- namespace internal
- {
+ } // end of namespace mlc::internal::form
+
typedef char yes_;
struct no_ { char dummy[2]; };
@@ -125,7 +114,7 @@
template<class T, class U>
struct check
- : public value<bool,( is_a__check_result_ )>
+ : public bool_<( mlc_internal_is_a__check_result_ )>
{
};
};
@@ -148,7 +137,7 @@
template<class T, template < class > class U>
struct check
- : public value<bool,( is_a__check_result_ )>
+ : public bool_<( mlc_internal_is_a__check_result_ )>
{
};
};
@@ -171,7 +160,7 @@
template<class T, template < class,class > class U>
struct check
- : public value<bool,( is_a__check_result_ )>
+ : public bool_<( mlc_internal_is_a__check_result_ )>
{};
};
@@ -193,7 +182,7 @@
template<class T, template < template < class > class > class U>
struct check
- : public value<bool,( is_a__check_result_ )>
+ : public bool_<( mlc_internal_is_a__check_result_ )>
{};
};
@@ -215,26 +204,24 @@
template<class T, template < template < class,class > class > class U>
struct check
- : public value<bool,( is_a__check_result_ )>
+ : public bool_<( mlc_internal_is_a__check_result_ )>
{};
};
- } // end of internal
-} // end of mlc
+ } // end of namespace mlc::internal
-// private macros: do _not_ use them
-# define is_a__2nd_is_meta(T,U) mlc::internal::is_a_< id_of_typeform(U) >::check<T, U >
+} // end of namespace mlc
-// client macros
-# define id_of_typeform(T) sizeof(mlc::form::get<T >())
-template <class T>
-struct id_ { typedef T ret; };
+/// 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 > >
+
+# define mlc_is_a_(T, U) \
+mlc::internal::wrap< mlc::internal::is_a_< sizeof(mlc::internal::form::get<U >()) >::check<T, U > >
-// FIXME: can we get rid of mlc::wrap ?
-# define mlc_is_a(T, U) mlc::internal::wrap<typename mlc::internal::is_a_< id_of_typeform(U) >::check<T, U > >
-# define mlc_is_a_(T, U) mlc::internal::wrap<mlc::internal::is_a_< id_of_typeform(U) >::check<T, U > >
-#endif // ndef METALIC_IS_A_HH
+#endif // ! METALIC_IS_A_HH
Index: metalic/mlc/value.hh
--- metalic/mlc/value.hh (revision 0)
+++ metalic/mlc/value.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2005 EPITA Research and Development Laboratory
+// Copyright (C) 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
@@ -28,23 +28,155 @@
#ifndef METALIC_VALUE_HH
# define METALIC_VALUE_HH
+# include <mlc/type.hh>
+
+
+
+/// Internal macros.
+
+
+# define mlc_internal_decl_unsigned_(Type, TypeName) \
+namespace internal \
+{ \
+ template <Type val> \
+ struct value_ <Type, val> : public abstract::unsigned_integer \
+ { \
+ typedef Type type; \
+ static const Type value = val; \
+ }; \
+} \
+template <Type val> \
+struct TypeName : public internal::value_<Type, val> {}
+
+
+# define mlc_internal_decl_signed_(Type, TypeName) \
+namespace internal \
+{ \
+ template <Type val> \
+ struct value_ <Type, val> : public abstract::signed_integer \
+ { \
+ typedef Type type; \
+ static const Type value = val; \
+ }; \
+} \
+template <Type val> \
+struct TypeName : public internal::value_<Type, val> {}
+
+
+
-/*! \namespace mlc
-** \brief mlc namespace.
-*/
namespace mlc {
- /// Class that defines a mlc value as a type (for instance mlc::value<int,3>).
- template <typename T, T v>
- struct value
- {
- static const T val = v;
- value() {}
- operator T() const { return v; }
+ namespace abstract {
+
+ /*! \class mlc::abstract::value
+ **
+ ** Abstract base class for mlc types that represent values.
+ **
+ ** For instance, the types mlc::true_ and mlc::int_<51> derive
+ ** from this abstraction.
+ */
+
+ struct value : public type
+ {
+ };
+
+ /// Abstractions for integer values as types.
+
+ struct integer : public value {};
+ struct unsigned_integer : public integer {};
+ struct signed_integer : public integer {};
+
+ } // end of namespace mlc::abstract
+
+
+ namespace internal
+ {
+
+ /*! \class mlc::internal::value_<T, val>
+ **
+ ** Base class for values to be represented by types. This class
+ ** is in the internal namespace so you should not use it. Its
+ ** purpose is only to factor code for derived classes that are not
+ ** internal (for instance, mlc::true_ or mlc::int_<51>).
+ **
+ ** Design note: this class can only be used for values that can be
+ ** a parameter (mlc::internal::value_<float, 3.14f> is incorrect).
+ **
+ ** Parameter T is the type of the value. Parameter val is the
+ ** value itself.
+ **
+ ** \see mlc/bool.hh
+ */
+
+ template <typename T, T val>
+ struct value_ : public abstract::value
+ {
+ /*! \typedef type
+ **
+ ** Gives the regular type of the value. For instance,
+ ** mlc::true_::type is bool and mlc::int_<51>::type is int.
+ */
+ typedef T type;
+
+ /*! \member value
+ **
+ ** Gives the regular value. For instance,
+ ** mlc::true_::value is true and mlc::int_<51>::value is 51.
+ */
+ static const T value = val;
+ };
+
+ } // end of namespace mlc::internal
+
+
+
+
+ // Dedicated sub-classes for builtin types.
+
+ mlc_internal_decl_unsigned_( unsigned char, uchar_ );
+ mlc_internal_decl_unsigned_( unsigned short, ushort_ );
+ mlc_internal_decl_unsigned_( unsigned int, uint_ );
+ mlc_internal_decl_unsigned_( unsigned long, ulong_ );
+
+ mlc_internal_decl_signed_( signed char, schar_ );
+ mlc_internal_decl_signed_( signed short, short_ );
+ mlc_internal_decl_signed_( signed int, int_ );
+ mlc_internal_decl_signed_( signed long, long_ );
+
+
+ // char
+
+ template <char c>
+ struct char_ : public internal::value_<char, c>
+ {
};
+ // Boolean values as types are defined elsewhere
+ // see: mlc/bool.hh
+
+
+} // end of namespace mlc
+
+
+# include <mlc/bool.hh>
+# 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
Index: metalic/mlc/flags.hh
--- metalic/mlc/flags.hh (revision 0)
+++ metalic/mlc/flags.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2005 EPITA Research and Development Laboratory
+// Copyright (C) 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
@@ -25,39 +25,78 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef METALIC_TYPES_HH
-# define METALIC_TYPES_HH
+#ifndef METALIC_FLAGS_HH
+# define METALIC_FLAGS_HH
+# include <mlc/type.hh>
-/*! \namespace mlc
-** \brief mlc namespace.
-*/
namespace mlc {
- /*! \class undefined_type
+ namespace abstract {
+
+ /*! \class mlc::abstract::flag
+ **
+ ** Abstract base class for types that are only flags.
+ **
+ ** Example: mlc::undefined is a mlc::abstract::flag.
+ */
+
+ struct flag : public type {};
+
+ } // end of namespace mlc::abstract
+
+
+ /*! \class mlc::undefined
+ **
+ ** Flag class to state that a type is undefined, that is, declared
+ ** but not defined.
+ **
+ ** Sample use: you want to define a trait to get the signed version
+ ** of a type T. For that, you write:
+ **
+ ** template <typename T>
+ ** struct signed_type_of
+ ** {
+ ** typedef mlc::undefined 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.
+ */
+ struct undefined : public abstract::flag {};
+
+ struct unknown : public abstract::flag {};
+
+ 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).
+ **
+ ** 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.
**
- ** Type by default. If the programmer forgets to define a type,
- ** actually this type should however exists and should be set to
- ** undefined_type.
+ ** \see mlc_typedef
*/
- class undefined_type { private: undefined_type(); };
+ struct not_found : public abstract::flag {};
- // FIXME: document.
- class unknown_type { private: unknown_type(); };
- class no_type { private: no_type(); };
- class default_type { private: default_type(); };
-
- namespace internal
- {
- class not_found { private: not_found(); };
- class not_ok { private: not_ok(); };
- } // end of namespace mlc::internal
+ // FIXME: add corresponding is_* types
} // end of namespace mlc
-#endif // ! METALIC_TYPES_HH
+#endif // ! METALIC_FLAGS_HH
Index: metalic/mlc/cmp.hh
--- metalic/mlc/cmp.hh (revision 0)
+++ metalic/mlc/cmp.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2001, 2002, 2003, 2004, 2005 EPITA Research and Development Laboratory
+// 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
@@ -29,62 +29,44 @@
# define METALIC_CMP_HH
# include <mlc/bool.hh>
-# include <mlc/types.hh>
+# include <mlc/is_a.hh>
/// Macros mlc_eq and mlc_neq.
-# define mlc_eq(T1, T2) mlc::eq<T1, T2>
-# define mlc_neq(T1, T2) mlc::neq<T1, T2>
-
-# define mlc_is_found(T) mlc::is_found<(T)>
-# define mlc_is_not_found(T) mlc::is_not_found<(T)>
+# define mlc_eq( T1, T2) mlc::eq_ <T1, T2>
+# define mlc_neq(T1, T2) mlc::neq_<T1, T2>
namespace mlc
{
+
/// Equality test between a couple of types.
template <typename T1, typename T2>
- struct eq : public value<bool, false>
+ struct eq_ : private and_< is_not_value<T1>, is_not_value<T2> >::ensure_type,
+ public false_
{
};
template <typename T>
- struct eq <T, T> : public value<bool, true>
+ struct eq_ <T, T> : private is_not_value<T>::ensure_type,
+ public true_
{
};
+
/// Inequality test between a couple of types.
template <typename T1, typename T2>
- struct neq : public value<bool, true>
- {
- };
-
- template <typename T>
- struct neq <T, T> : public value<bool, false>
- {
- };
-
- /// Tests is_found and is_not_found (sugar) upon a type.
-
- template <typename T>
- struct is_found : public neq <T, internal::not_found>
+ struct neq_ : private and_< is_not_value<T1>, is_not_value<T2> >::ensure_type,
+ public true_
{
};
template <typename T>
- struct is_not_found : public eq <T, internal::not_found>
- {
- };
-
-
-
- template <typename T>
- struct is_ok : public and_< and_< neq<T, internal::not_found>,
- neq<T, internal::not_ok> >,
- neq<T, undefined_type> >
+ struct neq_ <T, T> : private is_not_value<T>::ensure_type,
+ public false_
{
};