::rtype... > OPTYPE;
typedef typename OPTYPE::rtype rtype;
#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(1,BOOST_PP_INC(TRIQS_CLEF_MAXNARGS), IMPL, nil);
#undef AUX
#undef IMPL
};
// The general eval function for expressions
template
typename evaluator::rtype
eval (T const & ex, Pairs const &... pairs) { return evaluator()(ex, pairs...); }
#ifdef TRIQS_SHORT_CIRCUIT_NOT_IMPLEMENTED
// A short circuit if intersection of ph and is 0, no need to evaluate the whole tree......
template
template
typename std::enable_if< (ph_set::value & ph_set::value) !=0, typename evaluator,Pairs...>::rtype > ::type
eval (expr const & ex, Pairs const &... pairs) { return evaluator, Pairs...>()(ex, pairs...); }
template
typename std::enable_if< (ph_set::value & ph_set::value) ==0, expr > ::type
eval (expr const & ex, Pairs const &... pairs) { return ex; }
#endif
/* ---------------------------------------------------------------------------------------------------
* make_function : transform an expression to a function
* --------------------------------------------------------------------------------------------------- */
template< typename Expr, int... Is> struct make_fun_impl {
Expr ex; // keep a copy of the expression
make_fun_impl(Expr const & ex_) : ex(ex_) {}
// gcc 4.6 crashes (!!!) on the first variant
#define TRIQS_WORKAROUND_GCC46BUG
#ifndef TRIQS_WORKAROUND_GCC46BUG
template
typename evaluator...>::rtype
operator()(Args const &... args) const
{ return evaluator...>() ( ex, pair(args)...); }
#else
template struct __eval {
typedef evaluator...> eval_t;
typedef typename eval_t::rtype rtype;
rtype operator()(Expr const &ex , Args const &... args) const { return eval_t() ( ex, pair(args)...); }
};
template
typename __eval::rtype operator()(Args const &... args) const { return __eval() ( ex, args...); }
#endif
};
template struct ph_filter;
template struct ph_filter { static constexpr ull_t value = ph_filter::value & (~ (1ull< struct ph_filter { static constexpr ull_t value = x; };
template< typename Expr, int... Is> struct ph_set > { static constexpr ull_t value = ph_filter ::value, Is...>::value;};
template< typename Expr, int... Is> struct is_any_lazy > : std::integral_constant>::value !=0>{};
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>::type,Phs::index...>
make_function(Expr && ex, Phs...) { return {ex}; }
namespace result_of {
template< typename Expr, typename ... Phs> struct make_function {
typedef make_fun_impl::type>::type,Phs::index...> type;
};
}
/* --------------------------------------------------------------------------------------------------
* make_function
* x_ >> expression is the same as make_function(expression,x)
* --------------------------------------------------------------------------------------------------- */
template
make_fun_impl operator >> ( placeholder p, Expr&& ex) { return {ex}; }
/* ---------------------------------------------------------------------------------------------------
* Auto assign for ()
* --------------------------------------------------------------------------------------------------- */
// by default it is deleted = not implemented : every class has to define it...
template void triqs_clef_auto_assign (T,F) = delete;
// remove the ref_wrapper, terminal ...
template void triqs_clef_auto_assign (std::reference_wrapper R ,F && f) { triqs_clef_auto_assign(R.get(),std::forward(f));}
template void triqs_clef_auto_assign (expr const & t,F && f) { triqs_clef_auto_assign(std::get<0>(t.childs),std::forward(f));}
// auto assign of an expr ? (for chain calls) : just reuse the same operator
template
void triqs_clef_auto_assign (expr && ex, RHS const & rhs) { ex << rhs;}
template
void triqs_clef_auto_assign (expr const & ex, RHS const & rhs) { ex << rhs;}
// The case A(x_,y_) = RHS : we form the function (make_function) and call auto_assign (by ADL)
template
void operator<<(expr...> && ex, RHS && rhs) {
triqs_clef_auto_assign(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...));
}
template
void operator<<(expr...> const & ex, RHS && rhs) {
triqs_clef_auto_assign(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...));
}
// any other case e.g. f(x_+y_) = RHS etc .... which makes no sense : compiler will stop
template
void operator<<(expr && ex, RHS && rhs) = delete;
template
void operator<<(expr const & ex, RHS && rhs) = delete;
/* ---------------------------------------------------------------------------------------------------
* Auto assign for []
* --------------------------------------------------------------------------------------------------- */
// by default it is deleted = not implemented : every class has to define it...
template void triqs_clef_auto_assign_subscript (T,F) = delete;
// remove the ref_wrapper, terminal ...
template void triqs_clef_auto_assign_subscript (std::reference_wrapper R ,F && f)
{ triqs_clef_auto_assign_subscript(R.get(),std::forward(f));}
template void triqs_clef_auto_assign_subscript (expr const & t,F && f)
{ triqs_clef_auto_assign_subscript(std::get<0>(t.childs),std::forward(f));}
// auto assign of an expr ? (for chain calls) : just reuse the same operator
template
void triqs_clef_auto_assign_subscript (expr const & ex, RHS const & rhs) { ex << rhs;}
// Same thing for the [ ]
template
void operator<<(expr...> const & ex, RHS && rhs) {
triqs_clef_auto_assign_subscript(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...));
}
template
void operator<<(expr const & ex, RHS && rhs) = delete;
/* --------------------------------------------------------------------------------------------------
* Create a terminal node of an object. The reference is wrapped in a reference_wrapper...
* --------------------------------------------------------------------------------------------------- */
template expr::type >
make_expr(T && x){ return expr::type >(tags::terminal(), std::forward(x));}
template auto lazy (T && x) -> decltype (make_expr(std::ref(x))) { return make_expr(std::ref(x)); }
/* --------------------------------------------------------------------------------------------------
* Create a call node of an object
* The object can be kept as a : a ref, a copy, a view
* --------------------------------------------------------------------------------------------------- */
namespace result_of {
template< typename Obj, typename... Args > struct make_expr_call :
std::enable_if< is_any_lazy::value, expr::type, typename remove_cv_ref::type ...> > {};
}
template< typename Obj, typename... Args >
typename result_of::make_expr_call::type
make_expr_call(Obj&& obj, Args &&... args)
{ return typename result_of::make_expr_call::type (tags::function(),std::forward(obj), std::forward(args)...);}
/* --------------------------------------------------------------------------------------------------
* Create a [] call (subscript) node of an object
* The object can be kept as a : a ref, a copy, a view
* --------------------------------------------------------------------------------------------------- */
namespace result_of {
template< typename Obj, typename Arg> struct make_expr_subscript :
std::enable_if< is_any_lazy::value, expr::type, typename remove_cv_ref::type> > {};
}
template< typename Obj, typename Arg>
typename result_of::make_expr_subscript::type
make_expr_subscript(Obj&& obj, Arg && arg)
{ return typename result_of::make_expr_subscript::type (tags::subscript(),std::forward(obj), std::forward(arg));}
/* --------------------------------------------------------------------------------------------------
* function class : stores any expression polymorphically
* f(x_,y_ ) = an expression associates this expression dynamically to f, which
* can then be used as a std::function of the same signature...
* --------------------------------------------------------------------------------------------------- */
template class function;
template class function : tags::function_class {
typedef std::function std_function_type;
mutable std::shared_ptr _exp; // CLEAN THIS MUTABLE ?
mutable std::shared_ptr < std_function_type > _fnt_ptr;
public:
function():_fnt_ptr(new std_function_type ()){}
template
explicit function(Expr const & _e, X... x) : _exp(new Expr(_e)),_fnt_ptr(new std_function_type(make_function(_e, x...))){}
ReturnType operator()(T const &... t) const { return (*_fnt_ptr)(t...);}
template< typename... Args>
typename triqs::clef::result_of::make_expr_call::type
operator()( Args&&... args ) const { return triqs::clef::make_expr_call (*this,args...);}
template friend void triqs_clef_auto_assign (function const & x, RHS rhs) {
* (x._fnt_ptr) = std_function_type (rhs);
x._exp = std::shared_ptr (new typename std::remove_cv::type (rhs.ex));
}
};
/* --------------------------------------------------------------------------------------------------
* The macro to make any function lazy
* TRIQS_CLEF_MAKE_FNT_LAZY (Arity,FunctionName ) : creates a new function in the triqs::lazy namespace
* taking expressions (at least one argument has to be an expression)
* The lookup happens by ADL, so IT MUST BE USED IN THE triqs::lazy namespace
* --------------------------------------------------------------------------------------------------- */
#define TRIQS_CLEF_MAKE_FNT_LAZY(name)\
struct name##_lazy_impl { \
template