
https://svn.lrde.epita.fr/svn/oln/trunk/extended Index: ChangeLog from Thierry Geraud <theo@lrde.epita.fr> Add material for literals, binding arguments, and static checks. * xtd/res.hh (xtd_res_0_ et al.): New; versions without typename. (xtd_internal_res_0, internal::get_res_0_unchecked): New; this equipment is for use in hierarchies to avoid partial definitions. * xtd/mexpr.hh: Add static assertions. * xtd/literal.hh (literal_): Rename as... (plain_literal_): ...this. (meta_literal_): New class. (literal_expr_): Add static assertions. (lit): New routine. (bind_1, bind_2, bind_3): New; method implementation for nary_fun_expr_<n, E>::bind_i. * xtd/arg.hh (xtd_nargs): Remove this duplicate. * xtd/args.hh (xtd_nargs, nargs_): Move to... * xtd/abstract/fun_expr.hh: ...this file. (fun_expr_<E>::nargs): Remove; xtd_nargs does it. (xtd_res_0): Replace by... (xtd_internal_res_0): ...this. (bind_1, bind_2, bind_3): New methods. * xtd/abstract/exact.hh: Remove; the routine exact_of has moved... * xtd/abstract/fun.hh: ...here. * xtd/abstract/plain_fun.hh (operator()): Add static check. * xtd/abstract/meta_fun.hh: Add static checks. * tests/id.cc: Add xfail tests. * tests/bind.cc: New. * tests/lit.cc: New. * tests/Makefile.am: Update. tests/Makefile.am | 6 + tests/bind.cc | 25 ++++++++ tests/id.cc | 4 - tests/lit.cc | 25 ++++++++ xtd/abstract/fun.hh | 17 +++++ xtd/abstract/fun_expr.hh | 116 +++++++++++++++++++++++++++++++++++-- xtd/abstract/meta_fun.hh | 86 ++++++++++++++++++++++++++-- xtd/abstract/plain_fun.hh | 28 ++++++++- xtd/arg.hh | 6 - xtd/args.hh | 31 ++-------- xtd/literal.hh | 141 ++++++++++++++++++++++++++++++++++++++++++++-- xtd/mexpr.hh | 109 +++++++++++++++++++++++++++++++---- xtd/res.hh | 21 ++++++ 13 files changed, 552 insertions(+), 63 deletions(-) Index: xtd/res.hh --- xtd/res.hh (revision 439) +++ xtd/res.hh (working copy) @@ -82,11 +82,25 @@ // macros # define xtd_res_0(F) typename xtd::internal::get_res_<F>::ret +# define xtd_res_0_(F) xtd::internal::get_res_<F>::ret + # define xtd_res_1(F, A1) typename xtd::internal::get_res_<F, A1>::ret +# define xtd_res_1_(F, A1) xtd::internal::get_res_<F, A1>::ret + # define xtd_res_2(F, A1, A2) typename xtd::internal::get_res_<F, A1, A2>::ret +# define xtd_res_2_(F, A1, A2) xtd::internal::get_res_<F, A1, A2>::ret + # define xtd_res_3(F, A1, A2, A3) typename xtd::internal::get_res_<F, A1, A2, A3>::ret +# define xtd_res_3_(F, A1, A2, A3) xtd::internal::get_res_<F, A1, A2, A3>::ret # define xtd_expr_res(F, Args) typename xtd::internal::get_expr_res_<F, Args>::ret +# define xtd_expr_res_(F, Args) xtd::internal::get_expr_res_<F, Args>::ret + + + +// internal so do not use it; prefer xtd_res_0(F) +# define xtd_internal_res_0(F) typename xtd::internal::get_res_0_unchecked<F>::ret + namespace xtd @@ -198,6 +212,13 @@ }; + template <typename F> + struct get_res_0_unchecked + { + typedef mlc_ret(xtd::res_<F>) ret; + }; + + // a single arg template <typename F, typename A1> Index: xtd/mexpr.hh --- xtd/mexpr.hh (revision 439) +++ xtd/mexpr.hh (working copy) @@ -30,12 +30,14 @@ # include <mlc/case.hh> # include <mlc/assert.hh> +# include <mlc/logic.hh> # include <mlc/is_a.hh> -# include <xtd/args.hh> -# include <xtd/res.hh> # include <xtd/abstract/nary_fun.hh> # include <xtd/abstract/fun_expr.hh> +# include <xtd/args.hh> +# include <xtd/res.hh> +# include <xtd/literal.hh> @@ -47,6 +49,13 @@ namespace ERROR { + struct MIXED_ARGUMENTS_IN_CALLING_A_BINARY_META_FUNCTION__EXPR_VALUE; + struct MIXED_ARGUMENTS_IN_CALLING_A_BINARY_META_FUNCTION__VALUE_EXPR; + + struct MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR1; + struct MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR2; + struct MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR3; + struct FIXME; } // end of namespace xtd::ERROR @@ -86,7 +95,13 @@ template <typename F> struct m0expr_ - : public abstract::nary_fun_expr_< 0, m0expr_<F> > + : private mlc::assert_< mlc_is_a(F, abstract::nary_fun_<0>), + ERROR::FIXME >, + + private mlc::assert_< mlc_is_a(F, abstract::meta_fun_), + ERROR::FIXME >, + + public abstract::nary_fun_expr_< 0, m0expr_<F> > { const F f; @@ -120,6 +135,9 @@ template <typename F, typename Expr> struct nargs_< m1expr_<F, Expr> > + + : private mlc::assert_< mlc_is_a(Expr, abstract::fun_expr_), + xtd::ERROR::FIXME > { static const unsigned ret = xtd_nargs(Expr); }; @@ -141,7 +159,16 @@ typename Expr> struct m1expr_ - : public abstract::nary_fun_expr_< xtd_nargs(Expr), + : private mlc::assert_< mlc_is_a(F, abstract::nary_fun_<1>), + ERROR::FIXME >, + + private mlc::assert_< mlc_is_a(F, abstract::meta_fun_), + ERROR::FIXME >, + + private mlc::assert_< mlc_is_a(Expr, abstract::fun_expr_), + xtd::ERROR::FIXME >, + + public abstract::nary_fun_expr_< xtd_nargs(Expr), m1expr_<F, Expr> > { typedef m1expr_<F, Expr> self; @@ -159,7 +186,7 @@ expr(exact_of(expr)) {} - m1expr_(const F& f, + m1expr_(const F& f, // FIXME: constraint? const abstract::fun_expr_<Expr>& expr) : f(f), expr(exact_of(expr)) @@ -189,6 +216,10 @@ template <typename F, typename Expr1, typename Expr2> struct nargs_< m2expr_<F, Expr1, Expr2> > + + : private mlc::assert_< mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_) >, + xtd::ERROR::FIXME > { static const unsigned ret = n_max< xtd_nargs(Expr1), xtd_nargs(Expr2) >::ret; @@ -212,7 +243,17 @@ typename Expr1, typename Expr2> struct m2expr_ - : public abstract::nary_fun_expr_< xtd_nargs(mlc_comma_2(m2expr_<F, Expr1, Expr2>)), + : private mlc::assert_< mlc_is_a(F, abstract::nary_fun_<2>), + ERROR::FIXME >, + + private mlc::assert_< mlc_is_a(F, abstract::meta_fun_), + ERROR::FIXME >, + + private mlc::assert_< mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_) >, + xtd::ERROR::FIXME >, + + public abstract::nary_fun_expr_< xtd_nargs(mlc_comma_2(m2expr_<F, Expr1, Expr2>)), m2expr_<F, Expr1, Expr2> > { typedef m2expr_<F, Expr1, Expr2> self; @@ -264,6 +305,11 @@ template <typename F, typename Expr1, typename Expr2, typename Expr3> struct nargs_< m3expr_<F, Expr1, Expr2, Expr3> > + + : private mlc::assert_< mlc::and_list_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_), + mlc_is_a(Expr3, abstract::fun_expr_) >, + xtd::ERROR::FIXME > { static const unsigned ret = n_max< xtd_nargs(Expr1), n_max< xtd_nargs(Expr2), @@ -289,7 +335,18 @@ typename Expr1, typename Expr2, typename Expr3> struct m3expr_ - : public abstract::nary_fun_expr_< xtd_nargs(mlc_comma_3(m3expr_<F, Expr1, Expr2, Expr3>)), + : private mlc::assert_< mlc_is_a(F, abstract::nary_fun_<3>), + ERROR::FIXME >, + + private mlc::assert_< mlc_is_a(F, abstract::meta_fun_), + ERROR::FIXME >, + + private mlc::assert_< mlc::and_list_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_), + mlc_is_a(Expr3, abstract::fun_expr_) >, + xtd::ERROR::FIXME >, + + public abstract::nary_fun_expr_< xtd_nargs(mlc_comma_3(m3expr_<F, Expr1, Expr2, Expr3>)), m3expr_<F, Expr1, Expr2, Expr3> > { typedef m3expr_<F, Expr1, Expr2, Expr3> self; @@ -358,15 +415,25 @@ }; + // meta_nary_fun_<2, F>::operator()(const fun_expr_<Expr1>& expr1, // const fun_expr_<Expr2>& expr2) const + template <typename F, typename Expr1, typename Expr2> struct case_< tag::meta_2ary_fun_operator, mlc::valist_<F, Expr1, Expr2>, 1 > - : public mlc::where_< mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), - mlc_is_a(Expr2, abstract::fun_expr_) > > + : public mlc::where_< mlc::or_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_) > >, + + private mlc::assert_< mlc::implies_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_) >, + xtd::ERROR::MIXED_ARGUMENTS_IN_CALLING_A_BINARY_META_FUNCTION__EXPR_VALUE >, + + private mlc::assert_< mlc::implies_< mlc_is_a(Expr2, abstract::fun_expr_), + mlc_is_a(Expr1, abstract::fun_expr_) >, + xtd::ERROR::MIXED_ARGUMENTS_IN_CALLING_A_BINARY_META_FUNCTION__VALUE_EXPR > { typedef m2expr_<F, Expr1, Expr2> res; @@ -377,9 +444,11 @@ res tmp(exact_of(*this_), expr1, expr2); return tmp; } + }; + // meta_nary_fun_<3, F>::operator()(const fun_expr_<Expr1>& expr1, // const fun_expr_<Expr2>& expr2, // const fun_expr_<Expr3>& expr3) const @@ -388,9 +457,27 @@ struct case_< tag::meta_3ary_fun_operator, mlc::valist_<F, Expr1, Expr2, Expr3>, 1 > - : public mlc::where_< mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), + : public mlc::where_< mlc::or_list_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_), + mlc_is_a(Expr3, abstract::fun_expr_) > >, + + // FIXME: try to get more precise error detections below... + + private mlc::assert_< mlc::implies_< mlc_is_a(Expr1, abstract::fun_expr_), mlc::and_< mlc_is_a(Expr2, abstract::fun_expr_), - mlc_is_a(Expr3, abstract::fun_expr_) > > > + mlc_is_a(Expr3, abstract::fun_expr_) > >, + xtd::ERROR::MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR1 >, + + private mlc::assert_< mlc::implies_< mlc_is_a(Expr2, abstract::fun_expr_), + mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr3, abstract::fun_expr_) > >, + xtd::ERROR::MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR2 >, + + private mlc::assert_< mlc::implies_< mlc_is_a(Expr3, abstract::fun_expr_), + mlc::and_< mlc_is_a(Expr1, abstract::fun_expr_), + mlc_is_a(Expr2, abstract::fun_expr_) > >, + xtd::ERROR::MIXED_ARGUMENTS_IN_CALLING_A_TERNARY_META_FUNCTION__EXPR3 > + { typedef m3expr_<F, Expr1, Expr2, Expr3> res; Index: xtd/literal.hh --- xtd/literal.hh (revision 439) +++ xtd/literal.hh (working copy) @@ -28,32 +28,45 @@ #ifndef EXTENDED_LITERAL_HH # define EXTENDED_LITERAL_HH +# include <mlc/assert.hh> +# include <mlc/is_a.hh> + # include <xtd/abstract/plain_fun.hh> +# include <xtd/abstract/meta_fun.hh> +# include <xtd/abstract/fun_expr.hh> namespace xtd { - /*! \class xtd::literal_<T> + namespace ERROR + { + struct FIXME; + + } // end of namespace xtd::ERROR + + + + /*! \class xtd::plain_literal_<T> ** ** FIXME: doc */ - template <typename T> struct literal_; // fwd decl + template <typename T> struct plain_literal_; // fwd decl template <typename T> - struct fun_traits_< literal_<T> > + struct fun_traits_< plain_literal_<T> > { typedef T res_type; }; template <typename T> - struct literal_ : public abstract::plain_nary_fun_< 0, literal_<T> > + struct plain_literal_ : public abstract::plain_nary_fun_< 0, plain_literal_<T> > { const T value; - literal_(const T& value) + plain_literal_(const T& value) : value(value) {} @@ -65,6 +78,39 @@ + // equipment for xtd::meta_literal_<T> + + template <typename T> struct meta_literal_; // fwd decl + + template <typename T> + struct res_< meta_literal_<T> > + { + typedef T ret; + }; + + + /*! \class xtd::meta_literal_<T> + ** + ** FIXME: doc + */ + + template <typename T> + struct meta_literal_ : public abstract::meta_nary_fun_< 0, meta_literal_<T> > + { + const T value; + + meta_literal_(const T& value) + : value(value) + {} + + T impl_calc() const + { + return this->value; + } + }; + + + // literal as fun expression // FIXME: this should be the only version (?) // FIXME: we should remove the plain version (?) @@ -90,7 +136,10 @@ template <typename T> struct literal_expr_ - : public abstract::nary_fun_expr_< 0, literal_expr_<T> > + : private mlc::assert_< mlc_is_not_a(T, abstract::fun_), + xtd::ERROR::FIXME >, + + public abstract::nary_fun_expr_< 0, literal_expr_<T> > { const T value; @@ -106,6 +155,86 @@ }; + // FIXME: doc + + template <typename T> + literal_expr_<T> lit(const T& value) + { + literal_expr_<T> tmp(value); + return tmp; + } + + +} // end of namespace xtd + + +# include <xtd/mexpr.hh> +# include <xtd/arg.hh> + + +namespace xtd +{ + + namespace abstract + { + + // nary_fun_expr_< 2, E >::bind_i + + template <typename E> + template <typename T> + m2expr_< E, literal_expr_<T>, arg_<2> > + nary_fun_expr_< 2, E >::bind_1(const T& value) const + { + typedef m2expr_< E, literal_expr_<T>, arg_<2> > ret; + ret tmp(exact_of(this), lit(value), arg_<2>()); + return tmp; + } + + template <typename E> + template <typename T> + m2expr_< E, arg_<1>, literal_expr_<T> > + nary_fun_expr_< 2, E >::bind_2(const T& value) const + { + typedef m2expr_< E, arg_<1>, literal_expr_<T> > ret; + ret tmp(exact_of(this), arg_<1>(), lit(value)); + return tmp; + } + + + // nary_fun_expr_< 3, E >::bind_i + + template <typename E> + template <typename T> + m3expr_< E, literal_expr_<T>, arg_<2>, arg_<3> > + nary_fun_expr_< 3, E >::bind_1(const T& value) const + { + typedef m3expr_< E, literal_expr_<T>, arg_<2>, arg_<3> > ret; + ret tmp(exact_of(this), lit(value), arg_<2>(), arg_<3>()); + return tmp; + } + + template <typename E> + template <typename T> + m3expr_< E, arg_<1>, literal_expr_<T>, arg_<3> > + nary_fun_expr_< 3, E >::bind_2(const T& value) const + { + typedef m3expr_< E, arg_<1>, literal_expr_<T>, arg_<3> > ret; + ret tmp(exact_of(this), arg_<1>(), lit(value), arg_<3>()); + return tmp; + } + + template <typename E> + template <typename T> + m3expr_< E, arg_<1>, arg_<2>, literal_expr_<T> > + nary_fun_expr_< 3, E >::bind_3(const T& value) const + { + typedef m3expr_< E, arg_<1>, arg_<2>, literal_expr_<T> > ret; + ret tmp(exact_of(this), arg_<1>(), arg_<2>(), lit(value)); + return tmp; + } + + } // end of namespace xtd::abstract + } // end of namespace xtd Index: xtd/args.hh --- xtd/args.hh (revision 439) +++ xtd/args.hh (working copy) @@ -29,23 +29,22 @@ # define EXTENDED_ARGS_HH # include <mlc/flags.hh> - - - -// FIXME: doc -// FIXME: this code should be rewritten to check that -// FIXME: xtd::nargs_<F>::ret is properly defined; see for -// FIXME: instance, the code of xtd_res or xtd_arg1... - -# define xtd_nargs(F) xtd::nargs_<F>::ret +# include <mlc/assert.hh> +# include <mlc/is_a.hh> namespace xtd { + namespace abstract { + + // fwd decl + template <typename E> struct fun_expr_; + + /*! \class xtd::abstract::args ** ** FIXME: Abstract base class for args_<..> @@ -61,20 +60,6 @@ - - /*! \class xtd::nargs_<F> - ** - ** FIXME: doc - ** FIXME: and add a mechanism so that the type of F is checked - ** FIXME: Cf. get_res0_ in xtd/abstract/meta_fun.hh - */ - - template <typename F> - struct nargs_; - - - - /*! \class xtd::args_<A1, ..> ** ** FIXME: to pack arguments Index: xtd/abstract/fun_expr.hh --- xtd/abstract/fun_expr.hh (revision 439) +++ xtd/abstract/fun_expr.hh (working copy) @@ -28,17 +28,23 @@ #ifndef EXTENDED_ABSTRACT_FUN_EXPR_HH # define EXTENDED_ABSTRACT_FUN_EXPR_HH +# include <mlc/flags.hh> # include <mlc/bool.hh> # include <mlc/is_a.hh> # include <mlc/comma.hh> # include <xtd/args.hh> # include <xtd/res.hh> -# include <xtd/abstract/exact.hh> # include <xtd/abstract/meta_fun.hh> +// FIXME: doc + +# define xtd_nargs(F) xtd::internal::get_nargs_<F>::ret + + + namespace xtd { @@ -47,13 +53,74 @@ { struct INTERNAL_ILL_FORMED_CALL_TO_xtd_fun_expr_eval; + struct SPECIALIZATION_OF_xtd_nargs_IS_FOR_xtd_fun_expr_ONLY; + struct SPECIALIZATION_OF_xtd_nargs_NOT_FOUND_FOR_AN_xtd_fun_expr; } // end of namespace xtd::ERROR + + /// Forward declarations. + /// \{ + namespace abstract { + template <typename E> class fun_expr_; + } + + template <typename F, typename Expr1, typename Expr2> + struct m2expr_; + + template <typename F, typename Expr1, typename Expr2, typename Expr3> + struct m3expr_; + + template <typename T> + struct literal_expr_; + + template <unsigned i> + struct arg_; + + /// \} + + + + /*! \class xtd::nargs_<F> + ** + ** FIXME: doc + ** FIXME: and add a mechanism so that the type of F is checked + ** FIXME: Cf. get_res0_ in xtd/abstract/meta_fun.hh + */ + + template <typename F> + struct nargs_ : public mlc::undefined + { + }; + + + namespace internal + { + + template <typename F> + struct get_nargs_ + + : // private mlc::assert_< mlc_is_a(F, xtd::abstract::fun_expr_), + // xtd::ERROR::SPECIALIZATION_OF_xtd_nargs_IS_FOR_xtd_fun_expr_ONLY >, + // FIXME: the static assertion above does *not* compile... + + private mlc::assert_< mlc_is_not_a(xtd::nargs_<F>, mlc::undefined), + xtd::ERROR::SPECIALIZATION_OF_xtd_nargs_NOT_FOUND_FOR_AN_xtd_fun_expr > + { + static const unsigned ret = xtd::nargs_<F>::ret; + }; + + } // end of xtd::internal + + + + namespace abstract + { + /*! \class xtd::abstract::fun_expr_<E> ** @@ -74,8 +141,6 @@ { public: - // evaluation: - template <typename Args> xtd_expr_res(E, Args) eval(const Args& as) const @@ -85,15 +150,15 @@ return exact_of(this)->impl_eval(as); } - // FIXME: the get_nargs method is obsolete; remove it! - unsigned nargs() const { return xtd_nargs(E); } - protected: fun_expr_() {} }; + + + /*! \class xtd::abstract::nary_fun_expr_<n, E> ** ** Abstract base class for function expressions with an explicit @@ -125,10 +190,19 @@ public meta_nary_fun_<0, E> { public: - xtd_res_0(E) impl_calc() const + + // the return type here is not xtd_res_0(E) + // the explanations are given with meta_nary_fun_<0, E>::operator()() + // in file xtd/abstract/meta_fun.hh + + xtd_internal_res_0(E) + impl_calc() const { return this->eval(mk_args()); } + + // no bind_i method here + protected: nary_fun_expr_() {} }; @@ -150,12 +224,16 @@ public meta_nary_fun_<1, E> { public: + template <typename A> xtd_res_1(E, A) impl_calc(const A& a) const { return this->eval(mk_args(a)); } + + // no bind_i method here + protected: nary_fun_expr_() {} }; @@ -177,12 +255,22 @@ public meta_nary_fun_<2, E> { public: + template <typename A1, typename A2> xtd_res_2(E, A1, A2) impl_calc(const A1& a1, const A2& a2) const { return this->eval(mk_args(a1, a2)); } + + template <typename T> + m2expr_< E, literal_expr_<T>, arg_<2> > + bind_1(const T& value) const; + + template <typename T> + m2expr_< E, arg_<1>, literal_expr_<T> > + bind_2(const T& value) const; + protected: nary_fun_expr_() {} }; @@ -204,12 +292,26 @@ public meta_nary_fun_<3, E> { public: + template <typename A1, typename A2, typename A3> xtd_res_3(E, A1, A2, A3) impl_calc(const A1& a1, const A2& a2, const A3& a3) const { return this->eval(mk_args(a1, a2, a3)); } + + template <typename T> + m3expr_< E, literal_expr_<T>, arg_<2>, arg_<3> > + bind_1(const T& value) const; + + template <typename T> + m3expr_< E, arg_<1>, literal_expr_<T>, arg_<3> > + bind_2(const T& value) const; + + template <typename T> + m3expr_< E, arg_<1>, arg_<2>, literal_expr_<T> > + bind_3(const T& value) const; + protected: nary_fun_expr_() {} }; Index: xtd/abstract/fun.hh --- xtd/abstract/fun.hh (revision 439) +++ xtd/abstract/fun.hh (working copy) @@ -51,6 +51,23 @@ } // end of namespace xtd::abstract + + + // FIXME: doc + + template <typename E> + const E* exact_of(const abstract::fun_<E>* f) + { + return (const E*)(const void*)(f); + } + + template <typename E> + const E& exact_of(const abstract::fun_<E>& f) + { + return *(const E*)(const void*)(&f); + } + + } // end of namespace xtd Index: xtd/abstract/plain_fun.hh --- xtd/abstract/plain_fun.hh (revision 439) +++ xtd/abstract/plain_fun.hh (working copy) @@ -29,11 +29,12 @@ # define EXTENDED_ABSTRACT_PLAIN_FUN_HH # include <mlc/flags.hh> -# include <mlc/bool.hh> // FIXME: should be assert.hh +# include <mlc/assert.hh> # include <mlc/is_a.hh> # include <mlc/typedef.hh> +# include <mlc/assert.hh> +# include <mlc/abort.hh> -# include <xtd/abstract/exact.hh> # include <xtd/abstract/fun.hh> # include <xtd/abstract/nary_fun.hh> @@ -70,18 +71,24 @@ struct YOU_SHOULD_NOT_DERIVE_FROM_xtd_plain_fun_BUT_FROM_xtd_plain_nary_fun; + struct FIXME; + + struct AN_xtd_plain_function_DOES_NOT_ACCEPT_AN_xtd_function_AS_ARGUMENT; + // FIXME: add error messages corresponding to definitions without sense // FIXME: such as having arg2 when the plain function is unary } // end of namespace xtd::ERROR + template <typename F> struct fun_traits_ : public mlc::undefined { // nothing }; + mlc_decl_typedef(arg_type); mlc_decl_typedef(arg1_type); @@ -94,8 +101,12 @@ namespace abstract { - // fwd decl + /// Forward declarations. + /// \{ template <unsigned n, typename E> class plain_nary_fun_; + template <typename E> class meta_fun_; + template <typename E> class fun_expr_; + /// \} @@ -157,10 +168,12 @@ public nary_fun_<0> { public: + xtd_res(E) operator()() const { return exact_of(this)->impl_op(); } + protected: plain_nary_fun_() {} }; @@ -185,10 +198,19 @@ xtd::ERROR::xtd_fun_traits_SHOULD_DEFINE_arg_type_FOR_AN_xtd_plain_nary_fun_WITH_n_BEING_1 > { public: + + template <typename F> + void operator()(const abstract::fun_<F>&) const + { + mlc::abort_< F, + xtd::ERROR::AN_xtd_plain_function_DOES_NOT_ACCEPT_AN_xtd_function_AS_ARGUMENT >::check(); + } + xtd_res(E) operator()(const xtd_arg(E)& arg) const { return exact_of(this)->impl_op(arg); } + protected: plain_nary_fun_() {} }; Index: xtd/abstract/meta_fun.hh --- xtd/abstract/meta_fun.hh (revision 439) +++ xtd/abstract/meta_fun.hh (working copy) @@ -28,10 +28,10 @@ #ifndef EXTENDED_ABSTRACT_META_FUN_HH # define EXTENDED_ABSTRACT_META_FUN_HH +# include <mlc/flags.hh> # include <mlc/pair.hh> # include <mlc/valist.hh> -# include <xtd/abstract/exact.hh> # include <xtd/abstract/fun.hh> # include <xtd/abstract/nary_fun.hh> # include <xtd/args.hh> @@ -46,6 +46,23 @@ namespace xtd { + + namespace ERROR + { + struct ARG_SHOULD_NOT_BE_A_PLAIN_FUN; + struct ARG1_SHOULD_NOT_BE_A_PLAIN_FUN; + struct ARG2_SHOULD_NOT_BE_A_PLAIN_FUN; + struct ARG3_SHOULD_NOT_BE_A_PLAIN_FUN; + + struct ARG_SHOULD_NOT_BE_A_META_NON_EXPR_FUN; + struct ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN; + struct ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN; + struct ARG3_SHOULD_NOT_BE_A_META_NON_EXPR_FUN; + + }// end of namespace xtd + + + // FIXME: document case stuff... namespace tag @@ -109,6 +126,8 @@ } // end of namespace xtd + + namespace xtd { @@ -169,7 +188,16 @@ { public: - xtd_res_0(E) + /* + ** This member is not templated so its behavior at compile-time + ** is different than meta_nary_fun_<n,E>::operator() where n > + ** 0. Here the return type should be known before the hierarchy + ** classes are fully compiled thus static assertions in the + ** macro xtd_res_0 do *not* work. An alternate macro is thus + ** in use. + */ + + xtd_internal_res_0(E) operator()() const { return exact_of(this)->impl_calc(); @@ -198,7 +226,16 @@ public: template <typename A> - struct case_ : public xtd::case_< xtd::tag::meta_1ary_fun_operator, + struct case_ + + : private mlc::assert_< mlc_is_not_a(A, xtd::abstract::plain_fun_), + xtd::ERROR::ARG_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A, xtd::abstract::meta_fun_), + mlc_is_a(A, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + public xtd::case_< xtd::tag::meta_1ary_fun_operator, mlc::pair_<E, A> >::ret {}; @@ -232,7 +269,23 @@ public: template <typename A1, typename A2> - struct case_ : public xtd::case_< xtd::tag::meta_2ary_fun_operator, + struct case_ + + : private mlc::assert_< mlc_is_not_a(A1, xtd::abstract::plain_fun_), + xtd::ERROR::ARG1_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A1, xtd::abstract::meta_fun_), + mlc_is_a(A1, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + private mlc::assert_< mlc_is_not_a(A2, xtd::abstract::plain_fun_), + xtd::ERROR::ARG2_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A2, xtd::abstract::meta_fun_), + mlc_is_a(A2, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + public xtd::case_< xtd::tag::meta_2ary_fun_operator, mlc::valist_<E, A1, A2> >::ret {}; @@ -265,7 +318,30 @@ public: template <typename A1, typename A2, typename A3> - struct case_ : public xtd::case_< xtd::tag::meta_3ary_fun_operator, + struct case_ + + : private mlc::assert_< mlc_is_not_a(A1, xtd::abstract::plain_fun_), + xtd::ERROR::ARG1_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A1, xtd::abstract::meta_fun_), + mlc_is_a(A1, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG1_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + private mlc::assert_< mlc_is_not_a(A2, xtd::abstract::plain_fun_), + xtd::ERROR::ARG2_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A2, xtd::abstract::meta_fun_), + mlc_is_a(A2, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG2_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + private mlc::assert_< mlc_is_not_a(A3, xtd::abstract::plain_fun_), + xtd::ERROR::ARG3_SHOULD_NOT_BE_A_PLAIN_FUN >, + + private mlc::assert_< mlc::implies_< mlc_is_a(A3, xtd::abstract::meta_fun_), + mlc_is_a(A3, xtd::abstract::fun_expr_) >, + xtd::ERROR::ARG3_SHOULD_NOT_BE_A_META_NON_EXPR_FUN >, + + public xtd::case_< xtd::tag::meta_3ary_fun_operator, mlc::valist_<E, A1, A2, A3> >::ret {}; Index: xtd/arg.hh --- xtd/arg.hh (revision 439) +++ xtd/arg.hh (working copy) @@ -36,16 +36,10 @@ - -# define xtd_nargs(F) xtd::nargs_<F>::ret - - - namespace xtd { - namespace internal { Index: tests/id.cc --- tests/id.cc (revision 439) +++ tests/id.cc (working copy) @@ -37,7 +37,9 @@ xtd::plain_id_<float> id_float; std::cout << id_float(5.1f) << std::endl; + // xfail tests: + // xtd::id(id_int); + // xtd::id(xtd::id); } - } Index: tests/bind.cc --- tests/bind.cc (revision 0) +++ tests/bind.cc (revision 0) @@ -0,0 +1,25 @@ +#include <iostream> + +#include <xtd/math.hh> + + +int main() +{ + using xtd::_1; + using xtd::_2; + using xtd::lit; + + (_1 + _2)(_1, _1); + + (_1 + _2)(_1, lit(1.f)); + + (_1 + _2).bind_2(1.f); + + std::cout << (_1 + _2)(5., 1.) << std::endl; + +// std::cout << (_1 + _2)(_1, 1.)(5.) << std::endl; + + // autre probl�me : + // std::cout << (_1 + 1)(5.f) << std::endl; + +} Index: tests/Makefile.am --- tests/Makefile.am (revision 439) +++ tests/Makefile.am (working copy) @@ -9,11 +9,15 @@ check_PROGRAMS = \ id \ + bind \ cast \ - cos + cos \ + lit id_SOURCES = id.cc +bind_SOURCES = bind.cc cast_SOURCES = cast.cc cos_SOURCES = cos.cc +lit_SOURCES = lit.cc TESTS = $(check_PROGRAMS) Index: tests/lit.cc --- tests/lit.cc (revision 0) +++ tests/lit.cc (revision 0) @@ -0,0 +1,25 @@ +#include <iostream> +#include <xtd/literal.hh> + + +int main() +{ + + { + xtd::plain_literal_<double> l(5.1); + } + + { + typedef xtd::meta_literal_<double> F; + F l(5.1); + // xtd_res_0_(F) tmp; + // int warning = tmp; + } + + { + xtd::literal_expr_<double> l(5.1); + } + + + std::cout << mlc_is_a_(xtd::meta_literal_<double>, xtd::abstract::meta_fun_)::eval::value << std::endl; +}