Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
Re: [Olena-patches] proto-1.0 391: Implementation of a denoising image processing algorithm : Non Local Means.
by Nicolas 09 Feb '06
by Nicolas 09 Feb '06
09 Feb '06
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
1
0
proto-1.0 391: Implementation of a denoising image processing algorithm : Non Local Means.
by Nicolas Widynski 09 Feb '06
by Nicolas Widynski 09 Feb '06
09 Feb '06
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 \
1
0
https://svn/svn/oln/prototypes/proto-1.0/olena
Index: ChangeLog
from Nicolas Widynski <nicolas.widynski(a)lrde.epita.fr>
Update laplacian convolution.
* oln/convolution/laplacian.hh: Update file.
laplacian.hh | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
Index: oln/convolution/laplacian.hh
--- oln/convolution/laplacian.hh (revision 389)
+++ oln/convolution/laplacian.hh (working copy)
@@ -45,13 +45,11 @@
namespace impl {
- // FIXME : type I must be a ntg::int_s8 u8...
-
template <typename I>
oln_type_of(I, concrete)
laplacian_(const abstract::image2d<I>& input)
{
- oln_type_of(I, concrete) lpl(input.size(), "laplacian second derivative");
+ oln_type_of(I, concrete) lpl(input.size(), "laplacian");
oln_type_of(I, fwd_piter) p(input.size());
oln_type_of(I, point) pt;
oln_type_of(I, value) v;
@@ -73,7 +71,7 @@
template <typename I>
oln_type_of(I, concrete)
- laplacian_(const abstract::image<I>& input)
+ laplacian(const abstract::image<I>& input)
{
return impl::laplacian_(input.exact());
}
1
0
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_
{
1
0
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)
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/metalic
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Static `if'.
* mlc/if.hh: New file.
if.hh | 41 ++++++++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 9 deletions(-)
Index: mlc/if.hh
--- mlc/if.hh (revision 0)
+++ mlc/if.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
@@ -31,8 +31,19 @@
# include <mlc/bool.hh>
-/// Macro mlc_if.
-# define mlc_if(Cond, Then, Else) typename mlc::if_<(Cond), (Then), (Else)>::ret
+/** \def mlc_if(Cond, Then, Else)
+ ** \brief Static `if' on types.
+ **
+ ** If \a Cond is true, evaluate to type \a Then, otherwise evaluate to
+ ** type \a Else.
+ **
+ ** \note \a Then and \a Else must be valid types, since they are both
+ ** evaluated, whatever the result of \a Cond.
+ **
+ */
+# define mlc_if(Cond, Then, Else) typename mlc::if_<Cond, Then, Else>::ret
+/// Likewise, without the leading \c typename keyword.
+# define mlc_if_(Cond, Then, Else) mlc::if_<Cond, Then, Else>::ret
namespace mlc
@@ -41,17 +52,23 @@
namespace internal
{
+ /// \brief Declare a static `if'.
+ /// \note Internal class, don't use it directly.
template <bool b, typename then_type, typename else_type>
- struct fun_if_;
+ struct if_;
+ /// \brief Specialization of mlc::internal::if_ when condition is true.
+ /// \note Internal class, don't use it directly.
template <typename then_type, typename else_type>
- struct fun_if_ <true, then_type, else_type>
+ struct if_ <true, then_type, else_type>
{
typedef then_type ret;
};
+ /// \brief Specialization of mlc::internal::if_ when condition is false.
+ /// \note Internal class, don't use it directly.
template <typename then_type, typename else_type>
- struct fun_if_ <false, then_type, else_type>
+ struct if_ <false, then_type, else_type>
{
typedef else_type ret;
};
@@ -59,14 +76,20 @@
} // end of namespace mlc::internal
+/** \brief Static `if' on types.
+ **
+ ** If \a Cond is true, evaluate to type \a Then, otherwise evaluate to
+ ** type \a Else. The \a ret member holds the result.
+ **
+ ** \note \a Then and \a Else must be valid types, since they are both
+ ** evaluated, whatever the result of \a Cond.
+ */
template <typename cond_type, typename then_type, typename else_type>
- struct if_ : public internal::fun_if_ < mlc_bool(cond_type), then_type, else_type >
+ struct if_ : public internal::if_ < mlc_bool(cond_type), then_type, else_type >
{
};
-
} // end of namespace mlc
-
#endif // ! METALIC_IF_HH
1
0
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_
{
};
1
0
https://svn.lrde.epita.fr/svn/oln/trunk
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Move Metalic-related entries in their own ChangeLog.
* metalic/mlc: Move Metalic-related entries...
* metalic/ChangeLog: ...here (new).
ChangeLog | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
Index: metalic/ChangeLog
--- metalic/ChangeLog (revision 0)
+++ metalic/ChangeLog (revision 0)
@@ -0,0 +1,42 @@
+2006-01-25 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.
+
+ * .: New.
+ * mlc: New.
+ * mlc/type.hh: New.
+ * 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.
+ * mlc/is_a.hh: New.
+ (form): Move in the internal namespace cause names are too long
+ for a decent client use.
+ * 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.
+ * 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.
+ * 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.
+ * mlc/typedef.hh: New.
1
0
25 Jan '06
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_
{
};
1
0
Hop, le premier commit de Olena 1.0. :)
(Désolé pour le mail en retard, je me suis raté avec Vcs.)
https://svn.lrde.epita.fr/svn/oln/trunk
ChangeLog | 6 ++++++
vcs/oln.rb | 16 ++++++++++++++++
2 files changed, 22 insertions(+)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add Vcs helper.
* vcs/oln.rb: New.
++ vcs/oln.rb (révision 382)
class Vcs
# See http://rubyforge.org/projects/vcs
# and http://vcs.rubyforge.org
protocol_version '0.1'
def olena_commit! ( *args )
common_commit!("<%= rev %>: <%= title %>", *args) do |subject|
mail!(:to => %w['olena-patches(a)lrde.epita.fr'], :subject => subject)
end
end
alias_command :olnci, :olena_commit
default_commit :olena_commit
end # class Vcs
2
3