proto-1.0 142: Add static checks of properties and impls.

2005-04-13 Thierry GERAUD <theo@tegucigalpa.lrde.epita.fr> * oln/core/typedefs.hh: New include. * oln/core/abstract/niter.hh: Add static checks of properties and impls. * oln/core/abstract/image_constness.hh (set): Change signature. * oln/core/abstract/image.hh: Likewise. * oln/core/abstract/piter.hh: Likewise. * oln/core/abstract/qiter.hh: Likewise. * oln/core/abstract/image_neighbness.hh: Likewise. * oln/core/abstract/point.hh: Likewise. (~point): Remove obsolete static checks. * oln/core/abstract/data_storage.hh: Likewise. * oln/core/abstract/iter.hh: Likewise. (~iter): Remove obsolete static checks. * oln/core/abstract/neighborhood.hh: Likewise. (name): Remove. * oln/core/abstract/window.hh: Likewise. * oln/core/abstract/size.hh: Likewise. * oln/core/abstract/dpoint.hh: Likewise. (operator==, operator!=): Change signature. * oln/core/1d/dpoint1d.hh: Likewise. * oln/core/2d/dpoint2d.hh: Likewise. * oln/core/3d/dpoint3d.hh: Likewise. * oln/core/abstract/grid.hh: Likewise. (dpoint_type, size_type): New properties. * oln/core/1d/grid1d.hh: Likewise. * oln/core/2d/grid2d.hh: Likewise. * oln/core/3d/grid3d.hh: Likewise. * oln/core/any/dpoint.hh: Likewise. * oln/core/gen/regular_window.hh (size_type): Update. * oln/morpho/dilation.hh: Fix macro. * oln/morpho/erosion.hh: Likewise. Index: oln/core/typedefs.hh =================================================================== --- oln/core/typedefs.hh (revision 141) +++ oln/core/typedefs.hh (working copy) @@ -32,6 +32,7 @@ # include <mlc/types.hh> +# include <mlc/cmp.hh> # include <mlc/typedef.hh> # include <mlc/properties.hh> # include <mlc/to_string.hh> Index: oln/core/abstract/niter.hh =================================================================== --- oln/core/abstract/niter.hh (revision 141) +++ oln/core/abstract/niter.hh (working copy) @@ -78,6 +78,12 @@ << "\t neighb_type = " << mlc_to_string(neighb_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< point_type >::ensure(); + mlc::is_ok< neighb_type >::ensure(); + } }; @@ -119,11 +125,8 @@ ~niter() { - { // impl_cast_point - typedef const point_type (E::*meth)() const; - meth adr = &E::impl_cast_point; - adr = 0; - } + get_props<category::niter, E>::ensure(); + mlc_check_method_impl(E, const point_type, cast_point, , const); } }; Index: oln/core/abstract/image_constness.hh =================================================================== --- oln/core/abstract/image_constness.hh (revision 141) +++ oln/core/abstract/image_constness.hh (working copy) @@ -89,6 +89,7 @@ /// typedef typedef oln_type_of(E, point) point_type; + typedef oln_type_of(E, value) value_type; /*! \brief Write the value \a v at \a p in the current image. @@ -99,8 +100,7 @@ ** \see value_box, abstract::image<I>::operator[](point) */ - template <typename V> - void set(const point_type& p, const V& v) + void set(const point_type& p, const value_type& v) { return this->exact().impl_set(p, v); } @@ -122,6 +122,10 @@ */ readwrite_image() {} + ~readwrite_image() + { +// mlc_check_method_impl_2(E, void, set, const point_type&, const value_type&, ); + } }; @@ -133,9 +137,9 @@ /// typedefs typedef typename image_impl<E>::D D; typedef oln_type_of(D, point) point_type; + typedef oln_type_of(D, value) value_type; - template <typename V> - void impl_set(const point_type& p, const V& v) + void impl_set(const point_type& p, const value_type& v) { this->exact().impl_set_ante(p, v); this->delegate().impl_set(p, v); @@ -144,11 +148,8 @@ // extra code; default is 'do nothing': - template <typename V> - void impl_set_ante(const point_type&, const V&) {} - - template <typename V> - void impl_set_post(const point_type&, const V&) {} + void impl_set_ante(const point_type&, const value_type&) {} + void impl_set_post(const point_type&, const value_type&) {} }; } // end of namespace oln::abstract::internal Index: oln/core/abstract/image.hh =================================================================== --- oln/core/abstract/image.hh (revision 141) +++ oln/core/abstract/image.hh (working copy) @@ -113,6 +113,8 @@ static void echo(std::ostream& ostr) { ostr << "props_of( oln::category::image, " << mlc_to_string(I) << " ) =" << std::endl + << "{" << std::endl + << "\t concrete_type = " << mlc_to_string(concrete_type) << std::endl << "\t value_type = " << mlc_to_string(value_type) << std::endl << "\t point_type = " << mlc_to_string(point_type) << std::endl @@ -131,9 +133,28 @@ << "\t image_constness_type = " << mlc_to_string(image_constness_type) << std::endl << "\t image_dimension_type = " << mlc_to_string(image_dimension_type) << std::endl - << std::endl; + << "}" << std::endl; } + static void ensure() + { + mlc::is_ok< concrete_type >::ensure(); + mlc::is_ok< value_type >::ensure(); + mlc::is_ok< point_type >::ensure(); + mlc::is_ok< size_type >::ensure(); + mlc::is_ok< piter_type >::ensure(); + mlc::is_ok< fwd_piter_type >::ensure(); + mlc::is_ok< bkd_piter_type >::ensure(); + + mlc::is_ok< value_storage_type >::ensure(); + mlc::is_ok< storage_type >::ensure(); + mlc::is_ok< delegated_type >::ensure(); + mlc::is_ok< neighb_type >::ensure(); + + mlc::is_ok< image_neighbness_type >::ensure(); + mlc::is_ok< image_constness_type >::ensure(); + mlc::is_ok< image_dimension_type >::ensure(); + } }; } // end of namespace oln @@ -303,10 +324,20 @@ } - /*! \brief Destructor (empty). + /*! \brief Destructor. */ - virtual ~image() {} + virtual ~image() + { + get_props<category::image, E>::ensure(); + // FIXME: static check fails because "pointer to member conversion via virtual base"... +// mlc_check_method_impl(E, const size_type&, size, , const); +// mlc_check_method_impl(E, unsigned long, npoints, , const); +// mlc_check_method_impl(E, bool, hold, const point_type&, const); +// mlc_check_method_impl(E, bool, hold_large, const point_type&, const); +// mlc_check_method_impl(E, const value_type, get, const point_type&, const); +// mlc_check_method_impl_2(E, void, resize_border, size_t, bool, const); + } Index: oln/core/abstract/piter.hh =================================================================== --- oln/core/abstract/piter.hh (revision 141) +++ oln/core/abstract/piter.hh (working copy) @@ -82,6 +82,12 @@ << "\t size_type = " << mlc_to_string(size_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< point_type >::ensure(); + mlc::is_ok< size_type >::ensure(); + } }; @@ -117,6 +123,10 @@ const size_type s_; point_type p_; + ~piter() + { + get_props<category::piter, E>::ensure(); + } }; } // end of namespace oln::abstract Index: oln/core/abstract/qiter.hh =================================================================== --- oln/core/abstract/qiter.hh (revision 141) +++ oln/core/abstract/qiter.hh (working copy) @@ -74,6 +74,11 @@ << "\t window_type = " << mlc_to_string(window_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< window_type >::ensure(); + } }; @@ -96,6 +101,11 @@ } const window_type& win_; + + ~qiter() + { + get_props<category::qiter, E>::ensure(); + } }; } // end of namespace oln::abstract Index: oln/core/abstract/grid.hh =================================================================== --- oln/core/abstract/grid.hh (revision 141) +++ oln/core/abstract/grid.hh (working copy) @@ -50,7 +50,8 @@ struct set_default_props < category::grid > { typedef mlc::undefined_type point_type; - typedef mlc::undefined_type dpoint_type; + typedef mlc::no_type dpoint_type; + typedef mlc::undefined_type size_type; typedef mlc::undefined_type coord_type; typedef mlc::undefined_type dimvalue_type; }; @@ -62,6 +63,7 @@ typedef oln_grd_type_of(G, point) point_type; typedef oln_grd_type_of(G, dpoint) dpoint_type; typedef oln_grd_type_of(G, coord) coord_type; + typedef oln_grd_type_of(G, size) size_type; typedef oln_grd_type_of(G, dimvalue) dimvalue_type; static void echo(std::ostream& ostr) @@ -71,9 +73,19 @@ << "\t point_type = " << mlc_to_string(point_type) << std::endl << "\t dpoint_type = " << mlc_to_string(dpoint_type) << std::endl << "\t coord_type = " << mlc_to_string(coord_type) << std::endl + << "\t size_type = " << mlc_to_string(size_type) << std::endl << "\t dimvalue_type = " << mlc_to_string(dimvalue_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< point_type >::ensure(); + mlc::is_ok< dpoint_type >::ensure(); + mlc::is_ok< coord_type >::ensure(); + mlc::is_ok< size_type >::ensure(); + mlc::is_ok< dimvalue_type >::ensure(); + } }; @@ -86,6 +98,10 @@ grid() {} + ~grid() + { + get_props<category::grid, E>::ensure(); + } }; } // end of namespace oln::abstract Index: oln/core/abstract/image_neighbness.hh =================================================================== --- oln/core/abstract/image_neighbness.hh (revision 141) +++ oln/core/abstract/image_neighbness.hh (working copy) @@ -54,9 +54,16 @@ } protected: + image_with_nbh() {} + + ~image_with_nbh() + { +// mlc_check_method_impl(E, const neighb_type&, nbh_get, , const); + } }; + template <typename E> struct image_without_nbh : public virtual image<E> { Index: oln/core/abstract/point.hh =================================================================== --- oln/core/abstract/point.hh (revision 141) +++ oln/core/abstract/point.hh (working copy) @@ -31,6 +31,7 @@ # include <mlc/any.hh> # include <mlc/if.hh> # include <mlc/cmp.hh> +# include <mlc/contract.hh> # include <oln/core/coord.hh> # include <oln/core/typedefs.hh> @@ -87,6 +88,12 @@ << "\t grid_type = " << mlc_to_string(grid_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< dpoint_type >::ensure(); + mlc::is_ok< grid_type >::ensure(); + } }; @@ -175,33 +182,14 @@ ~point() { - { // impl_eq - typedef bool (E::*meth)(const exact_type&) const; - meth adr = &E::impl_eq; - adr = 0; - } - { // impl_plus - typedef const exact_type (E::*meth)(const dpoint_type&) const; - meth adr = &E::impl_plus; - adr = 0; - } - { // impl_minus - typedef const dpoint_type (E::*meth)(const exact_type&) const; - meth adr = &E::impl_minus; - adr = 0; - } - { // impl_nth const - typedef const coord_type (E::*meth)(unsigned) const; - meth adr = &E::impl_nth; - adr = 0; - } - { // impl_nth - typedef coord_type& (E::*meth)(unsigned); - meth adr = &E::impl_nth; - adr = 0; - } - } + get_props<category::point, E>::ensure(); + mlc_check_method_impl(E, bool, eq, const exact_type&, const); + mlc_check_method_impl(E, const exact_type, plus, const dpoint_type&, const); + mlc_check_method_impl(E, const dpoint_type, minus, const exact_type&, const); + mlc_check_method_impl(E, const coord_type, nth, unsigned, const); + mlc_check_method_impl(E, coord_type&, nth, unsigned, ); + } }; Index: oln/core/abstract/dpoint.hh =================================================================== --- oln/core/abstract/dpoint.hh (revision 141) +++ oln/core/abstract/dpoint.hh (working copy) @@ -54,18 +54,18 @@ template <typename E> struct dpoint : public mlc::any<E> { + typedef E exact_type; /// Test equality of two dpoints. - // FIXME: doc... - bool operator==(const dpoint& rhs) const + bool operator==(const exact_type& rhs) const { return this->exact().impl_eq(rhs.exact()); } /// Test difference between two dpoints. - bool operator!=(const dpoint& rhs) const + bool operator!=(const exact_type& rhs) const { - return not this->operator==(rhs); + return ! this->operator==(rhs); } const coord_t nth(unsigned i) const @@ -83,12 +83,19 @@ protected: dpoint() {} + + ~dpoint() + { + mlc_check_method_impl(E, bool, eq, const exact_type&, const); + mlc_check_method_impl(E, const coord_t, nth, unsigned, const); + mlc_check_method_impl(E, coord_t&, nth, unsigned, ); + } }; + } // end of namespace abstract } // end of namespace oln - #endif // ! OLENA_CORE_ABSTRACT_DPOINT_HH Index: oln/core/abstract/data_storage.hh =================================================================== --- oln/core/abstract/data_storage.hh (revision 141) +++ oln/core/abstract/data_storage.hh (working copy) @@ -71,6 +71,13 @@ << "\t data_type = " << mlc_to_string(data_type) << std::endl << std::endl; } + + static void ensure() + { + mlc::is_ok< size_type >::ensure(); + mlc::is_ok< point_type >::ensure(); + mlc::is_ok< data_type >::ensure(); + } }; @@ -164,7 +171,25 @@ } protected: + data_storage() {} + + ~data_storage() + { + get_props<category::data_storage, E>::ensure(); + + mlc_check_method_impl(E, bool, has_data, , const); + mlc_check_method_impl(E, void, clear_data, , ); + mlc_check_method_impl(E, const size_type&, size, , const); + mlc_check_method_impl(E, void, resize, const size_type&, ); + mlc_check_method_impl(E, unsigned long, npoints, , const); + mlc_check_method_impl(E, bool, hold, const point_type&, const); + mlc_check_method_impl(E, const data_type, get, const point_type&, const); + mlc_check_method_impl(E, void, set_data, const data_type&, ); + mlc_check_method_impl(E, bool, hold_large, const point_type&, const); + mlc_check_method_impl_2(E, void, resize_border, size_t, bool, ); + mlc_check_method_impl_2(E, void, set, const point_type&, const data_type&, ); + } }; } // end of namespace abstract Index: oln/core/abstract/iter.hh =================================================================== --- oln/core/abstract/iter.hh (revision 141) +++ oln/core/abstract/iter.hh (working copy) @@ -80,26 +80,10 @@ ~iter() { - { // impl_start - typedef void (E::*meth)(); - meth adr = &E::impl_start; - adr = 0; - } - { // impl_next - typedef void (E::*meth)(); - meth adr = &E::impl_next; - adr = 0; - } - { // impl_is_valid - typedef bool (E::*meth)() const; - meth adr = &E::impl_is_valid; - adr = 0; - } - { // impl_invalidate - typedef void (E::*meth)(); - meth adr = &E::impl_invalidate; - adr = 0; - } + mlc_check_method_impl(E, void, start, , ); + mlc_check_method_impl(E, void, next, , ); + mlc_check_method_impl(E, bool, is_valid, , const); + mlc_check_method_impl(E, void, invalidate, , ); } }; Index: oln/core/abstract/neighborhood.hh =================================================================== --- oln/core/abstract/neighborhood.hh (revision 141) +++ oln/core/abstract/neighborhood.hh (working copy) @@ -78,6 +78,12 @@ << std::endl; } + static void ensure() + { + mlc::is_ok< dpoint_type >::ensure(); + mlc::is_ok< size_type >::ensure(); + mlc::is_ok< window_type >::ensure(); + } }; @@ -95,18 +101,14 @@ class neighborhood : public mlc::any__best_memory<E> { + // FIXME: rewrite this class + public: typedef oln_nbh_type_of(E, dpoint) dpoint_type; typedef E exact_type; - static std::string - name() - { - return std::string("neighborhood<") + exact_type::name() + ">"; - } - bool has(const dpoint_type& dp) const { @@ -196,10 +198,27 @@ dp_.reserve(size); }; + /// Attributes + std::vector<dpoint_type> dp_; max_accumulator<coord_t> delta_; + /// Destructor. + + ~neighborhood() + { + get_props<category::neighborhood, E>::ensure(); +// bool has(const dpoint_type& dp) const +// unsigned card() const +// exact_type& add(const dpoint_type& dp) +// dpoint_type dp(unsigned i) const +// const dpoint_type operator[](unsigned i) const +// coord_t get_delta() const +// coord_t delta_update(const dpoint_type& dp) + } + }; + } // end of abstract } // end of oln Index: oln/core/abstract/window.hh =================================================================== --- oln/core/abstract/window.hh (revision 141) +++ oln/core/abstract/window.hh (working copy) @@ -59,6 +59,7 @@ typedef mlc::undefined_type fwd_qiter_type; }; + template <typename W> struct get_props < category::window, W > { @@ -75,6 +76,13 @@ << "\t fwd_qiter_type = " << mlc_to_string(fwd_qiter_type) << std::endl << "}" << std::endl; } + + static void ensure() + { + mlc::is_ok< dpoint_type >::ensure(); + mlc::is_ok< size_type >::ensure(); + mlc::is_ok< fwd_qiter_type >::ensure(); + } }; @@ -93,8 +101,14 @@ struct window : public mlc::any<W> { protected: + window() {} + + ~window() + { + get_props<category::window, W>::ensure(); + } }; Index: oln/core/abstract/size.hh =================================================================== --- oln/core/abstract/size.hh (revision 141) +++ oln/core/abstract/size.hh (working copy) @@ -76,7 +76,14 @@ } protected: + size() {} + + ~size() + { + // FIXME: how to check a templated method? + } + }; Index: oln/core/1d/dpoint1d.hh =================================================================== --- oln/core/1d/dpoint1d.hh (revision 141) +++ oln/core/1d/dpoint1d.hh (working copy) @@ -69,16 +69,6 @@ return *this; } - bool operator==(const dpoint1d& rhs) const - { - return this->index_ == rhs.index_; - } - - bool operator!=(const dpoint1d& rhs) const - { - return this->index_ != rhs.index_; - } - const dpoint1d operator+(const dpoint1d& rhs) const { dpoint1d tmp(this->index() + rhs.index()); @@ -100,6 +90,11 @@ protected: + bool impl_eq(const dpoint1d& rhs) const + { + return this->index_ == rhs.index_; + } + const coord_t impl_nth(unsigned i) const { precondition(i == 0); Index: oln/core/1d/grid1d.hh =================================================================== --- oln/core/1d/grid1d.hh (revision 141) +++ oln/core/1d/grid1d.hh (working copy) @@ -38,6 +38,7 @@ struct grid1d; struct point1d; struct dpoint1d; + struct size1d; struct coord_t; // super type @@ -51,6 +52,7 @@ typedef point1d point_type; typedef dpoint1d dpoint_type; typedef coord_t coord_type; + typedef size1d size_type; typedef mlc::value<unsigned,1> dimvalue_type; }; Index: oln/core/2d/dpoint2d.hh =================================================================== --- oln/core/2d/dpoint2d.hh (revision 141) +++ oln/core/2d/dpoint2d.hh (working copy) @@ -76,16 +76,6 @@ return *this; } - bool operator==(const dpoint2d& rhs) const - { - return this->row_ == rhs.row_ && this->col_ == rhs.col_; - } - - bool operator!=(const dpoint2d& rhs) const - { - return ! this->operator==(rhs); - } - const dpoint2d operator+(const dpoint2d& rhs) const { dpoint2d tmp(this->row() + rhs.row(), this->col() + rhs.col()); @@ -110,6 +100,11 @@ protected: + bool impl_eq(const dpoint2d& rhs) const + { + return this->row_ == rhs.row_ && this->col_ == rhs.col_; + } + const coord_t impl_nth(unsigned i) const { precondition(i < 2); Index: oln/core/2d/grid2d.hh =================================================================== --- oln/core/2d/grid2d.hh (revision 141) +++ oln/core/2d/grid2d.hh (working copy) @@ -38,6 +38,7 @@ struct grid2d; struct point2d; struct dpoint2d; + struct size2d; struct coord_t; // super type @@ -50,6 +51,7 @@ { typedef point2d point_type; typedef dpoint2d dpoint_type; + typedef size2d size_type; typedef coord_t coord_type; typedef mlc::value<unsigned,2> dimvalue_type; }; Index: oln/core/3d/dpoint3d.hh =================================================================== --- oln/core/3d/dpoint3d.hh (revision 141) +++ oln/core/3d/dpoint3d.hh (working copy) @@ -68,16 +68,6 @@ return *this; } - bool operator==(const dpoint3d& rhs) const - { - return this->row_ == rhs.row_ && this->col_ == rhs.col_ && this->slice_ == rhs.slice_; - } - - bool operator!=(const dpoint3d& rhs) const - { - return ! this->operator==(rhs); - } - const dpoint3d operator+(const dpoint3d& rhs) const { dpoint3d tmp(this->slice() + rhs.slice(), this->row() + rhs.row(), this->col() + rhs.col()); @@ -104,6 +94,11 @@ protected: + bool impl_eq(const dpoint3d& rhs) const + { + return this->row_ == rhs.row_ && this->col_ == rhs.col_ && this->slice_ == rhs.slice_; + } + const coord_t impl_nth(unsigned i) const { precondition(i < 3); Index: oln/core/3d/grid3d.hh =================================================================== --- oln/core/3d/grid3d.hh (revision 141) +++ oln/core/3d/grid3d.hh (working copy) @@ -38,6 +38,7 @@ struct grid3d; struct point3d; struct dpoint3d; + struct size3d; struct coord_t; // super type @@ -50,6 +51,7 @@ { typedef point3d point_type; typedef dpoint3d dpoint_type; + typedef size3d size_type; typedef coord_t coord_type; typedef mlc::value<unsigned,2> dimvalue_type; }; Index: oln/core/any/dpoint.hh =================================================================== --- oln/core/any/dpoint.hh (revision 141) +++ oln/core/any/dpoint.hh (working copy) @@ -47,18 +47,6 @@ { template <typename D> - bool operator==(const abstract::dpoint<D>& rhs) const - { - return true; - } - - template <typename D> - bool operator!=(const abstract::dpoint<D>& rhs) const - { - return false; - } - - template <typename D> const any_dpoint operator+(const abstract::dpoint<D>& rhs) const { return any_dpoint(); @@ -72,6 +60,28 @@ return any_dpoint(); } + friend class abstract::dpoint<any_dpoint>; + + protected: + + bool impl_eq(const any_dpoint& rhs) const + { + return true; + } + + const coord_t impl_nth(unsigned i) const + { + precondition(0); + return 0; + } + + coord_t& impl_nth(unsigned i) + { + static coord_t dummy = coord_t(); + precondition(0); + return dummy; + } + }; } // end of namespace oln @@ -82,7 +92,21 @@ return ostr << "any"; } +template <typename D> +bool operator==(const oln::abstract::dpoint<D>& lhs, + const oln::any_dpoint& rhs) +{ + return true; +} +template <typename D> +bool operator!=(const oln::abstract::dpoint<D>& lhs, + const oln::any_dpoint& rhs) +{ + return false; +} + + # include <oln/core/any/point.hh> Index: oln/core/gen/regular_window.hh =================================================================== --- oln/core/gen/regular_window.hh (revision 141) +++ oln/core/gen/regular_window.hh (working copy) @@ -51,6 +51,7 @@ { typedef oln_grd_type_of(G, point) point_type; typedef oln_grd_type_of(G, dpoint) dpoint_type; + typedef oln_grd_type_of(G, size) size_type; typedef regular_fwd_qiter<G> fwd_qiter_type; // typedef regular_fwd_dpiter<G> fwd_dpiter_type; // FIXME: later... }; @@ -175,5 +176,7 @@ } +# include <oln/core/gen/regular_fwd_qiter.hh> + #endif // OLENA_CORE_GEN_REGULAR_WINDOW_HH Index: oln/morpho/dilation.hh =================================================================== --- oln/morpho/dilation.hh (revision 141) +++ oln/morpho/dilation.hh (working copy) @@ -170,7 +170,7 @@ void impl_run() { - mlc::eq<oln_type_of(I, size), oln_type_of(W, size)>::ensure(); + mlc::eq<oln_type_of(I, size), oln_wn_type_of(W, size)>::ensure(); output_type tmp(this->input.size()); // FIXME: trick this->output = tmp; Index: oln/morpho/erosion.hh =================================================================== --- oln/morpho/erosion.hh (revision 141) +++ oln/morpho/erosion.hh (working copy) @@ -160,7 +160,7 @@ void impl_run() { - mlc::eq<oln_type_of(I, size), oln_type_of(W, size)>::ensure(); + mlc::eq<oln_type_of(I, size), oln_wn_type_of(W, size)>::ensure(); output_type tmp(this->input.size()); // FIXME: trick this->output = tmp;
participants (1)
-
Thierry GERAUD