https://svn.lrde.epita.fr/svn/oln/trunk/metalic
I had to help the compiler regarding mlc_is_a (within a template context).
Tell me if the tests fail because of this change.
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add mlc::any.
* mlc/contract.hh: New (imported from Olena proto-1.0).
* mlc/any.hh: New (imported from Olena proto-1.0).
Aesthetic changes.
(any__simple): New class.
* mlc/is_a.hh (mlc_is_a, mlc_is_not_a): Use the `template' keyword
to remove an ambiguity w.r.t the nature of the template struct
`ret' within mlc::form::of.
* tests/any.cc: New test.
* tests/Makefile.am (check_PROGRAMS): Add any.
(any_SOURCES): New.
mlc/Makefile.am | 1
mlc/any.hh | 78 +++++++++++++++++++----------
mlc/contract.hh | 12 +---
mlc/is_a.hh | 8 ++-
tests/Makefile.am | 2
tests/any.cc | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 209 insertions(+), 35 deletions(-)
Index: tests/Makefile.am
--- tests/Makefile.am (revision 448)
+++ tests/Makefile.am (working copy)
@@ -8,6 +8,7 @@
# when oln.m4 is available in the distribution.
check_PROGRAMS = \
+ any \
case \
if \
is_a \
@@ -17,6 +18,7 @@
switch \
typedef
+any_SOURCES = any.cc
case_SOURCES = case.cc
if_SOURCES = if.cc
is_a_SOURCES = is_a.cc
Index: tests/any.cc
--- tests/any.cc (revision 0)
+++ tests/any.cc (revision 0)
@@ -0,0 +1,143 @@
+/// Test mlc::any.
+
+#include <mlc/any.hh>
+#include <mlc/cmp.hh>
+#include <mlc/assert.hh>
+#include <mlc/logic.hh>
+#include <mlc/is_a.hh>
+
+// FIXME: Test other flavors of mlc::any.
+
+/* Linear hierachy.
+
+ - Abstractions.
+
+ mlc::any<Exact>
+ ^
+ |
+ A<Exact>
+ ^
+ |
+ B<Exact>
+ ^
+ |
+ Exact
+
+
+ - Concrete class C, deriving from B.
+
+ mlc::any<C>
+ ^
+ |
+ A<C>
+ ^
+ |
+ B<C>
+ ^
+ |
+ C
+
+*/
+
+template <typename Exact>
+struct A : public mlc::any__simple< Exact > {};
+
+template <typename Exact>
+struct B : public A< Exact > {};
+
+struct C : public B<C> {};
+
+
+/* A more complex hierarchy (several subclasses, diamond inheritance).
+
+ - Abstractions.
+
+ mlc::any<Exact>
+ ^
+ |
+ T<Exact>
+ ^ ^ ^
+ / | \
+ / | \
+ U<Exact> X<Exact> Y<Exact>
+ ^ ^ ^
+ | | |
+ Exact Exact Exact
+
+ - Concrete classes V and Z, deriving from U and from X and Y resp.
+
+
+ mlc::any<Z> mlc::any<Z>
+ ^ ^
+ | |
+ T<Z> T<Z>
+ ^ ^
+ | / \
+ U<Z> X<Z> Y<Z>
+ ^ ^ ^
+ | \ /
+ V Z
+
+*/
+
+template <typename Exact>
+struct T : public mlc::any__simple< Exact > {};
+
+template <typename Exact>
+struct U : public T< Exact > {};
+
+struct V : public U<V> {};
+
+template <typename Exact>
+struct X : virtual public T< Exact > {};
+
+template <typename Exact>
+struct Y : virtual public T< Exact > {};
+
+struct Z : public X<Z>, public Y<Z> {};
+
+// The struct enclosing these two functions (methods) is used to
+// factor the code w.r.t. the tested hierarchy.
+template <template < class > class Top>
+struct assuming_top_class_is
+{
+ template <template < class > class T, typename E>
+ static void
+ test_exact_is_a(Top<E>& a)
+ {
+ typedef typeof(a.exact()) exact_type;
+
+ mlc::assert_< mlc::eq_<exact_type, E> >::check();
+ mlc::assert_< mlc_is_a(exact_type, T) >::check();
+ };
+
+ template <template <class> class T, typename E>
+ static void
+ test_exact_is_not_a(Top<E>& a)
+ {
+ typedef typeof(a.exact()) exact_type;
+
+ mlc::assert_< mlc::eq_<exact_type, E> >::check();
+ mlc::assert_< mlc_is_not_a(exact_type, T) >::check();
+ }
+};
+
+int
+main()
+{
+ C c;
+ assuming_top_class_is<A>::test_exact_is_a<A>(c);
+ assuming_top_class_is<A>::test_exact_is_a<B>(c);
+
+ Z z;
+ assuming_top_class_is<T>::test_exact_is_a<T>(z);
+ assuming_top_class_is<T>::test_exact_is_a<X>(z);
+ assuming_top_class_is<T>::test_exact_is_a<Y>(z);
+
+ X<Z> x;
+ assuming_top_class_is<T>::test_exact_is_a<T>(x);
+ // Bad branch.
+ assuming_top_class_is<T>::test_exact_is_not_a<U>(x);
+ // Bad hierachy.
+ assuming_top_class_is<T>::test_exact_is_not_a<B>(x);
+}
Index: mlc/any.hh
--- mlc/any.hh (revision 0)
+++ mlc/any.hh (working copy)
@@ -1,4 +1,5 @@
-// 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,19 +30,21 @@
#ifndef METALIC_ANY_HH
# define METALIC_ANY_HH
-# include <mlc/contract.hh>
+/// \file mlc/any.hh
+/// \brief Implementation of mlc::any classes (top of static hierachies).
-// abbrev
-#define any_mem(E) any <E, dispatch_policy::best_memory>
+# include <mlc/contract.hh>
+// \def Shortcut.
+#define any_mem(E) any<E, dispatch_policy::best_memory>
-// 'any' classes
namespace mlc
{
+ /// Tags selecting a dispatch for mlc::any.
struct dispatch_policy
{
struct best_speed;
@@ -50,14 +53,16 @@
};
- // any
-
+ /// Top class of a static hierachy.
template <typename E, typename Dispatch_Policy = dispatch_policy::simple>
struct any;
- // "best speed" version of 'any'
+ /*-----------------------.
+ | mlc::any__best_speed. |
+ `-----------------------*/
+ /// "Best speed" version of `any'.
template <typename E>
struct any <E,
dispatch_policy::best_speed>
@@ -72,7 +77,6 @@
}
/// Assignment (op=).
-
any& operator=(const any& rhs)
{
// do nothing
@@ -81,19 +85,19 @@
}
/// Copy Ctor.
-
any(const any& rhs) :
- exact_ptr(0) // safety
+ // For safety purpose.
+ exact_ptr(0)
{
- // this->exact_ptr is *not* copied
- // its value has to be set in subclasses copy ctors.
+ // this->exact_ptr is *not* copied; its value has to be set in
+ // subclasses copy ctors.
}
protected:
any(E* exact_ptr) : exact_ptr(exact_ptr) {}
virtual ~any() {}
- /// Only attribute.
+ /// Sole attribute.
E* exact_ptr;
};
@@ -106,14 +110,21 @@
any__best_speed(E* exact_ptr = 0) : super(exact_ptr) {}
};
- // "best memory" version of 'any'
- // FIXME:
- // We should test with autotools if the compiler allows us to write a
- // static_cast or not (diamond inheritance problem). gcc-2.95 gives a
- // different adress but not gcc-3.
- // On Mac OS X, the compilation fails with a strange link error if you
- // try to use the offset computation.
+ /*------------------------.
+ | mlc::any__best_memory. |
+ `------------------------*/
+
+ /// "Best memory" version of 'any'
+ /* FIXME:
+ We should test with autotools if the compiler allows us to write a
+ static_cast or not (diamond inheritance problem). gcc-2.95 gives a
+ different adress but not gcc-3.
+ On Mac OS X, the compilation fails with a strange link error if you
+ try to use the offset computation.
+
+ 2006-03-24 Roland: Investigate this bug/behavior of Apple's GCC.
+ This is not the first time that Apple GCC 3.3 behaves strangely. */
template <typename E>
struct any <E,
dispatch_policy::best_memory>
@@ -141,8 +152,10 @@
protected:
any() {}
- any(E* exact_ptr_does_not_exist_in_this_version); // safety
- virtual ~any() {} // FIXME: virtual for a "best memory" version!?
+ // For safety purpose.
+ any(E* exact_ptr_does_not_exist_in_this_version);
+ // FIXME: virtual for a "best memory" version!?
+ virtual ~any() {}
};
template <typename E>
@@ -155,15 +168,19 @@
# if not defined __GNUC__ || __GNUC__ < 3
template <typename E> const E any_mem(E)::exact_obj = E();
- template <typename E> const any_mem(E)& any_mem(E)::ref_exact_obj =
any_mem(E)::exact_obj;
+ template <typename E> const any_mem(E)& any_mem(E)::ref_exact_obj =
+ any_mem(E)::exact_obj;
template <typename E> const int any_mem(E)::exact_offset =
(const
char*)(void*)(&any_mem(E)::ref_exact_obj)
- (const
char*)(void*)(&any_mem(E)::exact_obj);
# endif
- // "simple" version of 'any'
+ /*-------------------.
+ | mlc::any__simple. |
+ `-------------------*/
+ /// "Simple" version of `any'.
template <typename E>
struct any <E,
dispatch_policy::simple>
@@ -176,7 +193,16 @@
}
protected:
any() {}
- any(E* exact_ptr_does_not_exist_in_this_version); // safety
+ // For safety purpose.
+ any(E* exact_ptr_does_not_exist_in_this_version);
+ };
+
+ template <typename E>
+ struct any__simple : public any<E, dispatch_policy::simple>
+ {
+ protected:
+ typedef any<E, dispatch_policy::simple> super;
+ any__simple() : super() {}
};
Index: mlc/is_a.hh
--- mlc/is_a.hh (revision 448)
+++ mlc/is_a.hh (working copy)
@@ -239,7 +239,9 @@
*/
# define mlc_is_a(T, U) \
-mlc::wrap_< typename mlc::is_a_< sizeof(mlc::form::of< U >()) >::ret<
T, U > >
+mlc::wrap_< \
+ typename mlc::is_a_< sizeof(mlc::form::of< U >()) >::template ret< T, U
> \
+>
# define mlc_is_a_(T, U) \
mlc::is_a_< sizeof(mlc::form::of< U >()) >::ret< T, U >
@@ -254,7 +256,9 @@
*/
# define mlc_is_not_a(T, U) \
-mlc::not_< typename mlc::is_a_<sizeof(mlc::form::of<U >())>::ret<T,U
> >
+mlc::not_< \
+ typename mlc::is_a_<sizeof(mlc::form::of<U >())>::template ret< T, U
> \
+>
# define mlc_is_not_a_(T, U) \
mlc::not_< mlc::is_a_< sizeof(mlc::form::of<U >())>::ret<T,U > >
Index: mlc/Makefile.am
--- mlc/Makefile.am (revision 448)
+++ mlc/Makefile.am (working copy)
@@ -2,6 +2,7 @@
mlcdir = $(includedir)/mlc
nobase_mlc_HEADERS = \
+ any.hh \
bool.hh \
case.hh \
cmp.hh \
Index: mlc/contract.hh
--- mlc/contract.hh (revision 0)
+++ mlc/contract.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2001, 2002, 2003, 2004, 2005 EPITA Research and Development Laboratory
+// Copyright (C) 2001, 2002, 2003, 2004, 2005 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,11 +29,10 @@
#ifndef METALIC_CONTRACT_HH
# define METALIC_CONTRACT_HH
+# include <cassert>
-# include <assert.h>
-
-// FIXME: a lot of code has been removed here
-// for simplification purpose only
+// FIXME: a lot of code has been removed here for simplification
+// purpose only.
# define assertion(expr) assert(expr)
# define invariant(expr) assert(expr)
@@ -40,7 +40,6 @@
# define postcondition(expr) assert(expr)
-
# define mlc_check_method_impl(WHERE, RETURN, NAME, ARG, CONST) \
{ \
typedef RETURN (WHERE::*meth)(ARG) CONST; \
@@ -58,5 +57,4 @@
} \
struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
-
#endif // ! METALIC_CONTRACT_HH