449: Add mlc::any.

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@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
participants (1)
-
Roland Levillain