ChangeLog | 16 + TODO | 17 + oln/convert/abstract/conversion.hh | 358 +++++++++++++++++++++++++++++++++++++ oln/convert/conversion.hh | 174 +++++++++++++++++ oln/convert/force.hh | 63 ++++++ oln/core/apply.hh | 30 ++- oln/funobj/compose.hh | 45 ++++ tests/convert/tests/force | 22 ++ 8 files changed, 717 insertions(+), 8 deletions(-)
Index: olena/ChangeLog from Roland Levillain roland@lrde.epita.fr
Add conversion abstractions.
* oln/convert/abstract/conversion.hh, oln/convert/conversion.hh: New files.
Add convert::force operator.
* oln/convert/force.hh: New file. * tests/convert/tests/force: New test.
* oln/funobj/compose.hh (f_::identity_): New functor. * oln/core/apply.hh: Update doxygen comments. * TODO: New file.
Index: olena/oln/convert/abstract/conversion.hh --- olena/oln/convert/abstract/conversion.hh (révision 0) +++ olena/oln/convert/abstract/conversion.hh (révision 0) @@ -0,0 +1,179 @@ +// 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 +// 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_CONVERT_ABSTRACT_CONVERSION_HH +# define OLENA_CONVERT_ABSTRACT_CONVERSION_HH + +# include <ntg/utils/debug.hh> +# include <functional> + +namespace oln { + + namespace convert { + /*! + ** \brief Base classes for conversion. + */ + namespace abstract { + + // fwd_decl + template <class Exact, class Base> + class conversion; + + template<class Result_Type, + class Exact, class Base> + struct conversion_to_type; + + template<class Argument_Type, class Result_Type, + class Exact, class Base> + struct conversion_from_type_to_type; + + template<class Conv> + struct conversion_traits; + + /*! \brief Internal purpose only. + */ + namespace internal { + /// Retrieve the result type of a conversion. + template <class Base, class T> + struct output {}; + + template <class Argument_Type, class Result_Type, + class Exact, class Base> + struct output<conversion_from_type_to_type<Argument_Type, Result_Type, Exact, Base >, Argument_Type> + { + typedef Result_Type ret; + }; + + template <class Result_Type, + class Exact, class Base, class T> + struct output<conversion_to_type<Result_Type, Exact, Base >, T> + { + typedef Result_Type ret; + }; + + } // end of namespace oln::convert::abstract::internal + + } // end of namespace oln::convert::abstract + + namespace abstract { + + /*! Base class for conversion. + ** + ** \note If you write an class derived from this one, you + ** must write the specialization of the output trait. + */ + template<class Exact, class Base> + struct conversion : public mlc::any< Exact > + { + static std::string + name() + { + return std::string("conversion<") + Exact::name() + ">"; + } + + public: + template<class T> + struct output + { + typedef typename internal::output<Base, T>::ret ret; + }; + + /// Call the conversion written in the exact class. + template <class T> + typename output<T>::ret + operator()(const T& in) const + { + return this->exact().doit(in); + } + + protected: + conversion() {} + }; + + /// Base class for the conversion to a specific type. + template<class Result_Type, class Exact, + class Base = conversion_to_type<Result_Type, Exact, Exact> > + struct conversion_to_type : + public conversion< Exact, Base > + { + /* Additionally define result_type. This is not required + in a conversion class (generally not possible to define). + But it's useful when it's available (like here) + because it make the conversion appear almost as Adaptable + Unary Function (it will just lack the argument_type, but + this typedef is not used very much.) */ + + typedef Result_Type result_type; + + static std::string + name() + { + // FIXME: Exact is not an integre type ! + return std::string("conversion_to_type<") + + ntg_name(Result_Type) + ", " + + Exact::name() + ">"; + } + + protected: + conversion_to_type() {} + }; + + /// Base class if both input and output types of the conversion + /// are fixed. + template<class Argument_Type, class Result_Type, class Exact, + class Base = conversion_from_type_to_type<Argument_Type, Result_Type, Exact, Exact> > + struct conversion_from_type_to_type: + public conversion_to_type< Result_Type, Exact , Base > + { + + /* By defining argument_type, and inheriting from result_type, + we comply to the STL concept of Adaptable Unary Function. */ + + typedef Argument_Type argument_type; + + static std::string + name() + { + // FIXME: Exact is not an integre type ! + return std::string("conversion_from_type_to_type<") + + ntg_name(Argument_Type) + ", " + + ntg_name(Result_Type) + ", " + + "FIXME: ntg_name(Exact)" + ">"; + } + + protected : + conversion_from_type_to_type() {} + }; + + } // end of namespace oln::convert::abstract + + } // end of namespace oln::convert + +} // end of namespace oln + + +#endif // OLENA_CONVERT_ABSTRACT_CONVERSION_HH Index: olena/oln/convert/conversion.hh --- olena/oln/convert/conversion.hh (révision 0) +++ olena/oln/convert/conversion.hh (révision 0) @@ -0,0 +1,174 @@ +// 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 +// 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_CONVERT_CONVERSION_HH +# define OLENA_CONVERT_CONVERSION_HH + +# include <oln/core/abstract/image.hh> +# include <oln/core/ch_value_type.hh> +# include <oln/funobj/abstract/unary.hh> +# include <oln/funobj/abstract/binary.hh> +# include <oln/convert/abstract/conversion.hh> + +namespace oln { + /*! + ** \brief Conversion implementation (for example cast, color, or + ** neighborhood to window). + */ + namespace convert { + + /// \brief Internal purpose only. + namespace internal { + template <typename C, typename UF> struct compconv1_; + template <typename C, typename BF> struct compconv2_; + } // end of namespace oln::convert::internal + + } // end of namespace oln::convert + + template <typename C, typename UF> + struct set_super_type < convert::internal::compconv1_<C, UF> > { typedef f_::abstract::unary< convert::internal::compconv1_<C, UF> > ret; }; + + template <typename C, typename BF> + struct set_super_type < convert::internal::compconv2_<C, BF> > { typedef f_::abstract::binary< convert::internal::compconv2_<C, BF> > ret; }; + + template <typename C, typename UF> + struct set_props < category::fun1, convert::internal::compconv1_<C, UF> > + { + typedef oln_fun1_type_of(UF, arg) arg_type; + typedef typename C::template output<oln_fun1_type_of(UF, res)>::ret + res_type; + }; + + template <typename C, typename BF> + struct set_props < category::fun2, convert::internal::compconv2_<C, BF> > + { + typedef oln_fun2_type_of(BF, left) left_type; + typedef oln_fun2_type_of(BF, right) right_type; + typedef typename C::template output<oln_fun2_type_of(BF, res)>::ret + res_type; + }; + + namespace convert { + + /*! Trait that returns the output of a conversion. + ** + ** convoutput queries the output type of conversion ConvType for + ** an input of type InputType. This comes handy when computing + ** the return type of a function which takes a conversion function + ** in argument. + ** + ** \note convoutput is exported in the namespace oln for convenience. + */ + template<class ConvType, class Base, class InputType> + struct convoutput + { + typedef typename abstract::conversion<ConvType, Base>::template output<InputType>::ret ret; + }; + + namespace internal { + + /*! Compose a conversion C and an unary functor UF, producing an + ** unary functor. + */ + template <class C, class UF> + struct compconv1_ : public oln_super2_of_(compconv1_<C, UF>) + { + typedef compconv1_<C, UF> self_type; + typedef oln_fun1_type_of(self_type, arg) arg_type; + typedef oln_fun1_type_of(self_type, res) res_type; + + compconv1_(const C& conv, const UF& func) : + conv_(conv.exact()), func_(func.exact()) + { + } + + const res_type impl_unop(const arg_type& arg) const + { + return conv_(func_(arg)); + } + + private: + const C conv_; + const UF func_; + }; + + /*! Compose a conversion C and a binary functor BF, producing + ** a binary functor. + */ + template <class C, class BF> + struct compconv2_ : public oln_super2_of_(compconv2_<C, BF>) + { + typedef compconv2_<C, BF> self_type; + typedef oln_fun2_type_of(self_type, left) left_type; + typedef oln_fun2_type_of(self_type, right) right_type; + typedef oln_fun2_type_of(self_type, res) res_type; + + compconv2_(const C& conv, const BF& func) : + conv_(conv.exact()), func_(func.exact()) + { + } + + const res_type impl_binop(const left_type& left, + const right_type& right) const + { + return conv_(func_(left, right)); + } + + private: + const C conv_; + const BF func_; + }; + + } // end of namespace oln::convert::internal + + /*! Friendly procedure that build an internal::compconv1_ with + ** type deduction. + */ + template <class C, class B, class UF> + internal::compconv1_<C, UF> + compconv1(const abstract::conversion<C, B>& conv, const UF &func) + { + return internal::compconv1_<C, UF>(conv.exact(), func); + } + + /*! Likewise for compconv2_. */ + template <class C, class B, class BF> + internal::compconv2_<C, BF> + compconv2(const abstract::conversion<C, B>& conv, const BF &func) + { + return internal::compconv2_<C, BF>(conv.exact(), func); + } + + } // end of namespace oln::convert + + // Export conversion and convouput into oln:: to simplify the + // writing of processings. + using convert::convoutput; + +} // end of namespace oln + +#endif // OLENA_CONVERT_CONVERSION_HH Index: olena/oln/convert/force.hh --- olena/oln/convert/force.hh (révision 0) +++ olena/oln/convert/force.hh (révision 0) @@ -0,0 +1,63 @@ +// 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 +// 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_CONVERT_FORCE_HH +# define OLENA_CONVERT_FORCE_HH + +# include <oln/convert/abstract/conversion.hh> +# include <ntg/utils/cast.hh> + +namespace oln { + + namespace convert { + + /*! Like cast::force, but as a conversion functor. */ + template<class Output> + struct force : public abstract::conversion_to_type< Output, force<Output> > + { + template< class Input > + Output + doit(const Input& v) const + { + return ntg::cast::force<Output>(v); + } + + static std::string + name() + { + // FIXME: Exact is not an integre type ! + return std::string("force<") + + ntg_name(Output) + ">"; + } + }; + + } // end of namespace oln::convert + +} // end of namespace oln + +#endif // OLENA_CONVERT_FORCE_HH Index: olena/tests/convert/tests/force --- olena/tests/convert/tests/force (révision 0) +++ olena/tests/convert/tests/force (révision 0) @@ -0,0 +1,22 @@ + // -*- C++ -*- +#include <ntg/int.hh> +#include <oln/funobj/arith.hh> +#include <oln/convert/conversion.hh> +#include <oln/convert/force.hh> + +using namespace oln; + +bool check() +{ + typedef ntg::int_u8 value_type; + f_::plus_<value_type, value_type> f_plus; + oln::convert::force<value_type> f_force; + + value_type a = 1; + value_type b = 2; + value_type c = convert::compconv2(f_force, f_plus)(a, b); + if (c != 3) + return true; + + return false; +} Index: olena/oln/funobj/compose.hh --- olena/oln/funobj/compose.hh (révision 216) +++ olena/oln/funobj/compose.hh (copie de travail) @@ -48,6 +48,11 @@ typedef oln_fun1_type_of(F2, arg) arg_type; };
+ + /*-----------------------------------. + | Composition of two unary functor. | + `-----------------------------------*/ + namespace f_ {
@@ -87,6 +92,46 @@ return f_::compose_uu_<UF1, UF2>(f1, f2); }
+ + /*-------------------. + | Identity functor. | + `-------------------*/ + + namespace f_ { + template <typename T> struct identity_; + } // end of namespace oln::f_ + + template <typename T> + struct set_super_type < f_::identity_<T> > { typedef f_::abstract::unary< f_::identity_<T> > ret; }; + + template <typename T> + struct set_props < category::fun1, f_::identity_<T> > + { + typedef T res_type; + typedef T arg_type; + }; + + namespace f_ + { + + /*! \class f_identity + ** + ** This functor returns its argument. + */ + template<class T> + struct identity_ : public oln_super_of_(f_::identity_<T>) + { + const T impl_unop(const T& t) const + { + return t; + } + }; + + typedef f_::unary_meta<f_::identity_> f_identity_type; + static f_identity_type f_identity; + + } // end of namespace oln::f_ + } // end of namespace oln
#endif // ! OLENA_CORE_FUNOBJ_CONVERSION_HH Index: olena/oln/core/apply.hh --- olena/oln/core/apply.hh (révision 216) +++ olena/oln/core/apply.hh (copie de travail) @@ -44,7 +44,8 @@ | Unary. | `--------*/
- /*! \brief Standard unary \a apply procedure. + /*! \brief Standard unary \a apply procedure of an + ** mlc:abstract::unary_function<F> ** ** Apply a function \a f to each element of \a input, the function ** is passed as a type and is instantiated. @@ -69,8 +70,12 @@ return output; }
- // version with oln::f_::abstract::unary<F> - + /*! \brief Standard unary \a apply procedure of an + ** oln::f_::abstract::unary + ** + ** Apply a function \a f to each element of \a input, the function + ** is passed as a type and is instantiated. + */ template <typename F, typename I> typename ch_value_type<I, oln_fun1_type_of(F, res)>::ret apply(const oln::f_::abstract::unary<F>& f, @@ -96,7 +101,8 @@ | Binary. | `---------*/
- /*! \brief Standard binary \a apply procedure. + /*! \brief Standard binary \a apply procedure of a + ** mlc:abstract::binary_function<F> ** ** Apply a function \a f to each pair of elements of ** \a input1 x \a input2. @@ -128,8 +134,12 @@ }
- // version with oln::f_::abstract::binary<F> - + /*! \brief Standard binary \a apply procedure of a + ** oln::f_::abstract::binary<F> + ** + ** Apply a function \a f to each pair of elements of + ** \a input1 x \a input2. + */ template <typename F, typename I1, typename I2> typename ch_value_type<I1, oln_fun2_type_of(F, res)>::ret apply2(const oln::f_::abstract::binary<F>& f, @@ -157,8 +167,12 @@ }
- // version with oln::f_::abstract::mbinary<F> - + /*! \brief Standard binary \a apply procedure of a + ** oln::f_::abstract::mbinary<F> + ** + ** Apply a function \a f to each pair of elements of + ** \a input1 x \a input2. + */ template <typename F, typename I1, typename I2> typename ch_value_type<I1, typename f_::mbinary_result<F, oln_type_of(I1, value), Index: olena/TODO --- olena/TODO (révision 0) +++ olena/TODO (révision 0) @@ -0,0 +1,17 @@ +* Possibly dead code + +** oln/core/compose.hh +Seems to be used nowhere. Morever, redundant with the new +oln/funobj/compose.hh, which deals with oln/funobj functors (whereas +the former handles functors à la STL). + + +* Lack of consistency in file naming + +** oln/level/compare.hh vs oln/ops/cmp.hh + + +Local Variables: +mode: outline +ispell-local-dictionary: "american" +End: Index: olena/oln/convert/abstract/conversion.hh --- olena/oln/convert/abstract/conversion.hh (révision 0) +++ olena/oln/convert/abstract/conversion.hh (révision 0) @@ -0,0 +1,179 @@ +// 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 +// 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_CONVERT_ABSTRACT_CONVERSION_HH +# define OLENA_CONVERT_ABSTRACT_CONVERSION_HH + +# include <ntg/utils/debug.hh> +# include <functional> + +namespace oln { + + namespace convert { + /*! + ** \brief Base classes for conversion. + */ + namespace abstract { + + // fwd_decl + template <class Exact, class Base> + class conversion; + + template<class Result_Type, + class Exact, class Base> + struct conversion_to_type; + + template<class Argument_Type, class Result_Type, + class Exact, class Base> + struct conversion_from_type_to_type; + + template<class Conv> + struct conversion_traits; + + /*! \brief Internal purpose only. + */ + namespace internal { + /// Retrieve the result type of a conversion. + template <class Base, class T> + struct output {}; + + template <class Argument_Type, class Result_Type, + class Exact, class Base> + struct output<conversion_from_type_to_type<Argument_Type, Result_Type, Exact, Base >, Argument_Type> + { + typedef Result_Type ret; + }; + + template <class Result_Type, + class Exact, class Base, class T> + struct output<conversion_to_type<Result_Type, Exact, Base >, T> + { + typedef Result_Type ret; + }; + + } // end of namespace oln::convert::abstract::internal + + } // end of namespace oln::convert::abstract + + namespace abstract { + + /*! Base class for conversion. + ** + ** \note If you write an class derived from this one, you + ** must write the specialization of the output trait. + */ + template<class Exact, class Base> + struct conversion : public mlc::any< Exact > + { + static std::string + name() + { + return std::string("conversion<") + Exact::name() + ">"; + } + + public: + template<class T> + struct output + { + typedef typename internal::output<Base, T>::ret ret; + }; + + /// Call the conversion written in the exact class. + template <class T> + typename output<T>::ret + operator()(const T& in) const + { + return this->exact().doit(in); + } + + protected: + conversion() {} + }; + + /// Base class for the conversion to a specific type. + template<class Result_Type, class Exact, + class Base = conversion_to_type<Result_Type, Exact, Exact> > + struct conversion_to_type : + public conversion< Exact, Base > + { + /* Additionally define result_type. This is not required + in a conversion class (generally not possible to define). + But it's useful when it's available (like here) + because it make the conversion appear almost as Adaptable + Unary Function (it will just lack the argument_type, but + this typedef is not used very much.) */ + + typedef Result_Type result_type; + + static std::string + name() + { + // FIXME: Exact is not an integre type ! + return std::string("conversion_to_type<") + + ntg_name(Result_Type) + ", " + + Exact::name() + ">"; + } + + protected: + conversion_to_type() {} + }; + + /// Base class if both input and output types of the conversion + /// are fixed. + template<class Argument_Type, class Result_Type, class Exact, + class Base = conversion_from_type_to_type<Argument_Type, Result_Type, Exact, Exact> > + struct conversion_from_type_to_type: + public conversion_to_type< Result_Type, Exact , Base > + { + + /* By defining argument_type, and inheriting from result_type, + we comply to the STL concept of Adaptable Unary Function. */ + + typedef Argument_Type argument_type; + + static std::string + name() + { + // FIXME: Exact is not an integre type ! + return std::string("conversion_from_type_to_type<") + + ntg_name(Argument_Type) + ", " + + ntg_name(Result_Type) + ", " + + "FIXME: ntg_name(Exact)" + ">"; + } + + protected : + conversion_from_type_to_type() {} + }; + + } // end of namespace oln::convert::abstract + + } // end of namespace oln::convert + +} // end of namespace oln + + +#endif // OLENA_CONVERT_ABSTRACT_CONVERSION_HH