diff --git a/triqs/clef/clef.hpp b/triqs/clef/clef.hpp index cb816103..6f51af06 100644 --- a/triqs/clef/clef.hpp +++ b/triqs/clef/clef.hpp @@ -46,21 +46,23 @@ namespace triqs { namespace clef { template struct force_copy_in_expr : force_copy_in_expr{}; template< class T > struct expr_storage_t {typedef T type;}; - template< class T > struct expr_storage_t : std::conditional::value, T ,std::reference_wrapper>{}; + template< class T > struct expr_storage_t : std::conditional::value, typename std::remove_const::type ,std::reference_wrapper>{}; template< class T > struct expr_storage_t {typedef T type;}; - + template< class T > struct expr_storage_t {typedef T type;}; + template< class T > struct expr_storage_t {typedef T type;}; + /* --------------------------------------------------------------------------------------------------- * Placeholder and corresponding traits * --------------------------------------------------------------------------------------------------- */ template class pair; // forward - // a placeholder is an empty struct, labelled by an int. + // a placeholder is an empty struct, labelled by an int. template struct placeholder { static_assert( (N>=0) && (N<64) , "Placeholder number limited to [0,63]"); static constexpr int index = N; template pair operator = (RHS && rhs) { return {std::forward(rhs)};} }; - + // placeholder will always be copied (they are empty anyway). template< int N > struct force_copy_in_expr> : std::true_type{}; @@ -90,11 +92,11 @@ namespace triqs { namespace clef { std::integral_constant::value || is_any_lazy::value> {}; template - constexpr bool ClefExpression() { return is_any_lazy::value;} + constexpr bool ClefExpression() { return is_any_lazy::value;} template struct is_clef_expression : is_any_lazy{}; -/* --------------------------------------------------------------------------------------------------- + /* --------------------------------------------------------------------------------------------------- * Node of the expression tree * --------------------------------------------------------------------------------------------------- */ template struct expr { @@ -136,7 +138,7 @@ namespace triqs { namespace clef { template struct operation; // a little function to clean the reference_wrapper - template U & _cl(U & x) { return x;} + template U _cl(U && x) { return std::forward(x);} template U & _cl(std::reference_wrapper x) { return x.get();} /// Terminal @@ -156,7 +158,7 @@ namespace triqs { namespace clef { #define TRIQS_CLEF_OPERATION(TAG,OP)\ namespace tags { struct TAG : binary_op { static const char * name() { return BOOST_PP_STRINGIZE(OP);} };}\ template<> struct operation {\ - template auto operator()(L const & l, R const & r) const DECL_AND_RETURN ( _cl(l) OP _cl(r));\ + template auto operator()(L && l, R && r) const DECL_AND_RETURN ( _cl(std::forward(l)) OP _cl(std::forward(r)));\ };\ template\ typename std::enable_if::value, expr::type,typename expr_storage_t::type> >::type \ @@ -189,7 +191,9 @@ namespace triqs { namespace clef { /// the only ternary node : expression if template<> struct operation { - template auto operator()(C const & c, A const & a, B const & b) const DECL_AND_RETURN (_cl(c) ? _cl(a): _cl(b)); + // A and B MUST be the same + template A operator()(C const & c, A const & a, B const & b) const {return _cl(c) ? _cl(a): _cl(b);} + //template auto operator()(C const & c, A const & a, B const & b) const DECL_AND_RETURN (_cl(c) ? _cl(a): _cl(b)); }; // operator is : if_else( Condition, A, B) template @@ -199,79 +203,76 @@ namespace triqs { namespace clef { /* --------------------------------------------------------------------------------------------------- * Evaluation of the expression tree. * --------------------------------------------------------------------------------------------------- */ + template struct _or; + template struct _or : std::integral_constant::value>{}; + template<> struct _or<> : std::false_type{}; - template struct operation2; - template struct operation2 { - typedef expr::type ...> rtype; - rtype operator()(Args const & ... args) const {return rtype {Tag(), args...};} - }; - template struct operation2 { - typedef typename std::remove_reference(Args...)>::type>::type rtype; - // remove the reference because of ternary if_else in which decltype returns a ref... - rtype operator()(Args const & ... args) const {return operation()(args...); } - }; - - // Generic case : do nothing (for the leaf of the tree except placeholder) + // Generic case : do nothing (for the leaf of the tree including placeholder) template struct evaluator{ - typedef T rtype; - rtype operator()(T const & k, Pairs const &... pairs) {return k;} + typedef is_any_lazy is_lazy; + T operator()(T const & k, Pairs const &... pairs) { return k;} }; // placeholder template struct evaluator< placeholder, pair, Pairs... > { typedef evaluator< placeholder, Pairs...> eval_t; - typedef typename eval_t::rtype rtype; - rtype operator()(placeholder, pair const &, Pairs const& ... pairs) { return eval_t()(placeholder(), pairs...);} + typedef typename eval_t::is_lazy is_lazy; + auto operator()(placeholder, pair const &, Pairs const& ... pairs) DECL_AND_RETURN( eval_t()(placeholder(), pairs...)); }; + template struct evaluator< placeholder, pair, Pairs... > { - typedef T const & rtype; - //typedef typename pair::value_type const & rtype; - rtype operator()(placeholder, pair const & p, Pairs const& ...) { return p.rhs;} + typedef std::false_type is_lazy; + T operator()(placeholder, pair const & p, Pairs const& ...) { return p.rhs;} + }; + + template struct operation2; + template struct operation2 { + template + expr::type ...> operator()(Args && ... args) const { + return {Tag(), std::forward(args)...}; + } + }; + template struct operation2 { + template + auto operator()(Args && ... args) const DECL_AND_RETURN( operation()(std::forward(args)...)); + void operator() (...) const {} }; // general expr node - template struct evaluator, Pairs...> { - typedef operation2::rtype... >::value, typename evaluator::rtype... > OPTYPE; - typedef typename OPTYPE::rtype rtype; + template struct evaluator_node_gal; + + template struct evaluator_node_gal<1, expr, Pairs...> { + typedef _or::is_lazy... > is_lazy; + typedef operation2 OPTYPE; + auto operator()(expr const & ex, Pairs const & ... pairs) const + DECL_AND_RETURN (OPTYPE()(eval(std::get<0>(ex.childs),pairs...))); + }; + + template struct evaluator_node_gal<2, expr, Pairs...> { + typedef _or::is_lazy... > is_lazy; + typedef operation2 OPTYPE; + auto operator()(expr const & ex, Pairs const & ... pairs) const + DECL_AND_RETURN (OPTYPE()(eval(std::get<0>(ex.childs),pairs...),eval(std::get<1>(ex.childs),pairs...))); + }; - // first done manually for clearer error messages ... - template< int arity = sizeof...(Childs)> - typename std::enable_if< arity==1, rtype>::type - operator()(expr const & ex, Pairs const & ... pairs) const - { return OPTYPE()(eval(std::get<0>(ex.childs),pairs...) );} - - template< int arity = sizeof...(Childs)> - typename std::enable_if< arity==2, rtype>::type - operator()(expr const & ex, Pairs const & ... pairs) const - { return OPTYPE()(eval(std::get<0>(ex.childs),pairs...),eval(std::get<1>(ex.childs),pairs...) );} - #define AUX(z,p,unused) eval(std::get

(ex.childs),pairs...) #define IMPL(z, NN, unused) \ - template< int arity = sizeof...(Childs)>\ - typename std::enable_if< arity==NN, rtype>::type\ - operator()(expr const & ex, Pairs const & ... pairs) const\ - { return OPTYPE()(BOOST_PP_ENUM(NN,AUX,nil));} - BOOST_PP_REPEAT_FROM_TO(3,BOOST_PP_INC(TRIQS_CLEF_MAXNARGS), IMPL, nil); + template struct evaluator_node_gal, Pairs...> {\ + typedef _or::is_lazy... > is_lazy;\ + typedef operation2 OPTYPE;\ + auto operator()(expr const & ex, Pairs const & ... pairs) const\ + DECL_AND_RETURN ( OPTYPE()(BOOST_PP_ENUM(NN,AUX,nil)));\ + }; + BOOST_PP_REPEAT_FROM_TO(3,BOOST_PP_INC(TRIQS_CLEF_MAXNARGS), IMPL, nil); #undef AUX #undef IMPL - }; -#ifdef TRIQS_CLEF_EVAL_SHORT_CIRCUIT - // A short circuit if intersection of ph and is 0, no need to evaluate the whole tree...... - // Seems useless, && the second eval is not correct if hte expression is a terminal. - template - typename std::enable_if< (ph_set::value & ph_set::value) !=0, typename evaluator::rtype > ::type - eval (T const & ex, Pairs const &... pairs) { return evaluator()(ex, pairs...); } + template + struct evaluator, Pairs...> : evaluator_node_gal, Pairs...>{}; - template - typename std::enable_if< (ph_set::value & ph_set::value) ==0, T const &> ::type - eval (T const & ex, Pairs const &... pairs) { return ex;} -#else // The general eval function for expressions template - typename evaluator::rtype - eval (T const & ex, Pairs const &... pairs) { return evaluator()(ex, pairs...); } -#endif + auto eval (T const & ex, Pairs const &... pairs) DECL_AND_RETURN( evaluator()(ex, pairs...)); /* --------------------------------------------------------------------------------------------------- * make_function : transform an expression to a function @@ -284,17 +285,15 @@ namespace triqs { namespace clef { // gcc 4.6 crashes (!!!) on the first variant #ifndef TRIQS_COMPILER_OBSOLETE_GCC template - typename evaluator...>::rtype - operator()(Args &&... args) const - { return evaluator...>() ( ex, pair{std::forward(args)}...); } + auto operator()(Args &&... args) const + DECL_AND_RETURN( evaluator...>() ( ex, pair{std::forward(args)}...)); #else template struct __eval { typedef evaluator...> eval_t; - typedef typename eval_t::rtype rtype; - rtype operator()(Expr const &ex , Args &&... args) const { return eval_t() ( ex, pair{std::forward(args)}...); } + auto operator()(Expr const &ex , Args &&... args) const DECL_AND_RETURN( return eval_t() ( ex, pair{std::forward(args)}...)); }; template - typename __eval::rtype operator()(Args &&... args) const { return __eval() ( ex, std::forward(args)...); } + auto operator()(Args &&... args) const DECL_AND_RETURN(return __eval() ( ex, std::forward(args)...)); #endif }; @@ -307,12 +306,6 @@ namespace triqs { namespace clef { template< typename Expr, int... Is> struct is_any_lazy > : std::integral_constant>::value !=0>{}; template< typename Expr, int... Is> struct force_copy_in_expr > : std::true_type{}; - template< typename Expr, int... Is,typename... Pairs> struct evaluator, Pairs...> { - typedef evaluator e_t; - typedef make_fun_impl rtype; - rtype operator()(make_fun_impl const & f, Pairs const & ... pairs) const { return rtype( e_t()(f.ex, pairs...));} - }; - template< typename Expr, typename ... Phs> make_fun_impl::type,Phs::index...> make_function(Expr && ex, Phs...) { return {ex}; } @@ -323,11 +316,17 @@ namespace triqs { namespace clef { }; } + template< typename Expr, int... Is,typename... Pairs> struct evaluator, Pairs...> { + typedef evaluator e_t; + typedef std::integral_constant >::value != ph_set::value> is_lazy; + auto operator()(make_fun_impl const & f, Pairs const & ... pairs) const DECL_AND_RETURN( make_function( e_t()(f.ex, pairs...),placeholder()...)); + }; + template struct ph_list {}; template ph_list var( placeholder ...) { return {};} template - auto operator >> (ph_list, Expr const & ex) DECL_AND_RETURN( make_function(ex, placeholder()...)); + auto operator >> (ph_list, Expr const & ex) DECL_AND_RETURN( make_function(ex, placeholder()...)); /* -------------------------------------------------------------------------------------------------- * make_function @@ -400,15 +399,15 @@ namespace triqs { namespace clef { void operator<<(expr...> const & ex, RHS && rhs) { triqs_clef_auto_assign_subscript(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...)); } - template + template void operator<<(expr...> && ex, RHS && rhs) { triqs_clef_auto_assign_subscript(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...)); } - template + template void operator<<(expr && ex, RHS && rhs) = delete; - template + template void operator<<(expr const & ex, RHS && rhs) = delete; /* -------------------------------------------------------------------------------------------------- @@ -433,7 +432,7 @@ namespace triqs { namespace clef { namespace _result_of { template< typename Obj, typename... Args > struct make_expr_call : std::enable_if< is_any_lazy::value, expr::type, typename expr_storage_t::type ...> > { - static_assert (((arity::value==-1) || (arity::value == sizeof...(Args))), "Object called with a wrong number of arguments"); + static_assert (((arity::value==-1) || (arity::value == sizeof...(Args))), "Object called with a wrong number of arguments"); }; } template< typename Obj, typename... Args > @@ -477,7 +476,7 @@ namespace triqs { namespace clef { auto operator()( Args&&... args ) const DECL_AND_RETURN(make_expr_call (*this,std::forward(args)...)); #else template< typename... Args> - typename _result_of::make_expr_call::type + typename _result_of::make_expr_call::type operator()( Args&&... args ) const { return make_expr_call (*this,args...);} #endif @@ -488,7 +487,7 @@ namespace triqs { namespace clef { }; template struct force_copy_in_expr > : std::true_type{}; - + /* -------------------------------------------------------------------------------------------------- * The macro to make any function lazy * TRIQS_CLEF_MAKE_FNT_LAZY (Arity,FunctionName ) : creates a new function in the triqs::lazy namespace @@ -504,7 +503,7 @@ namespace triqs { namespace clef { #ifndef TRIQS_COMPILER_OBSOLETE_GCC - #define TRIQS_CLEF_IMPLEMENT_LAZY_METHOD(TY,name)\ +#define TRIQS_CLEF_IMPLEMENT_LAZY_METHOD(TY,name)\ struct __clef_lazy_method_impl_##name { \ TY * _x;\ template auto operator()(A&&... a) const DECL_AND_RETURN (_x->name(std::forward(a)...));\