3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 13:53:40 +01:00

Revert a wrong fix in expression template for gf

This reverts the part of the commit 1906dc30a5
which introduced modifications in the expr templates of the Green's
functions. The commit had introduced some bugs and this revert
removes them (the expr templates will be taken care of fully in later
commits). This is a temporary fix for issues #18 and #25.

  reverted:   triqs/gfs/data_proxies.hpp
  reverted:   triqs/gfs/gf.hpp
  reverted:   triqs/gfs/gf_expr.hpp
This commit is contained in:
Michel Ferrero 2013-10-16 23:48:14 +02:00
parent 44bd729252
commit f4444f3b49
3 changed files with 120 additions and 78 deletions

View File

@ -42,7 +42,9 @@ namespace triqs { namespace gfs {
arrays::matrix_view_proxy<storage_view_t,0> operator()(storage_view_t & data, size_t i) const { return arrays::matrix_view_proxy<storage_view_t,0>(data,i); }
arrays::const_matrix_view_proxy<storage_view_t,0> operator()(storage_view_t const & data, size_t i) const { return arrays::const_matrix_view_proxy<storage_view_t,0>(data,i); }
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename RHS> static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward<RHS>(rhs);}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); }
};
@ -59,7 +61,9 @@ namespace triqs { namespace gfs {
auto operator()(storage_view_t & data,size_t i) const -> decltype(data(i)) { return data(i);}
auto operator()(storage_view_t const & data,size_t i) const -> decltype(data(i)) { return data(i);}
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename RHS> static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward<RHS>(rhs);}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); }
};
@ -78,6 +82,12 @@ namespace triqs { namespace gfs {
Tv & operator()(storage_view_t & data, size_t i) { return data[i];}
Tv const & operator()(storage_view_t const & data, size_t i) const { return data[i];}
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) {
//auto r = make_vector(rhs);
if (data.size() !=rhs.size()) TRIQS_RUNTIME_ERROR << "Size mismatch in gf assignment";
for (size_t i =0; i<data.size(); ++i) data[i] = rhs[i];
}
template<typename S, typename RHS> static void assign_with_resize (S & data, RHS && rhs) {data = utility::factory<storage_t>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) {for (size_t i =0; i<data.size(); ++i) data[i] = rhs;}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.clear(); for (auto & x : rhs.data()) data.push_back(x);}
};
@ -94,6 +104,8 @@ namespace triqs { namespace gfs {
auto operator()(storage_t & data, size_t i) DECL_AND_RETURN( data(i));
auto operator()(storage_t const & data, size_t i) const DECL_AND_RETURN( data(i));
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_with_resize (S & data, RHS && rhs) = delete;
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) = delete;
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) = delete;// { data = std::forward<RHS>(rhs);}
};

View File

@ -33,6 +33,7 @@ namespace triqs { namespace gfs {
using utility::factory;
using arrays::make_shape;
// GENERALISE matrxi TO DEFAULT
template<typename Variable, typename Opt=void> struct gf_mesh;
template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf; // the regular type
template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf_view; // the view type
@ -40,7 +41,7 @@ namespace triqs { namespace gfs {
// various implementation traits
namespace gfs_implementation { // never use using of this...
// evaluator regroup functions to evaluate the function.
// evaluator regroup functions to evaluate the function. Cf descriptors
template<typename Variable, typename Target, typename Opt> struct evaluator{ static constexpr int arity = 0;};
// closest_point mechanism
@ -59,7 +60,7 @@ namespace triqs { namespace gfs {
// this is used to specialize this part of the code to array of dim 3 (matrix gf), dim 1 (scalar gf) and vector (e.g. block gf, ...)
template<typename Variable, typename Target, typename Opt, typename Enable = void> struct data_proxy;
// This trait contains functions to read/write in hdf5 files. Can be specialized for some case (Cf block)
// This trait contains functions to read/write in hdf5 files. Can be specialized for some descriptor (Cf block)
template <typename Variable, typename Target, typename Opt> struct h5_name; // value is a const char *
template<typename Variable, typename Opt> struct h5_name<Variable,scalar_valued,Opt> { static std::string invoke(){ return h5_name<Variable,matrix_valued,Opt>::invoke() + "_s";}};
@ -82,6 +83,9 @@ namespace triqs { namespace gfs {
template <typename Variable, typename Target=matrix_valued, typename Opt=void, typename ... U>
gf_view<Variable,Target,Opt> make_gf_view(U && ... x) { return gfs_implementation::factories<Variable,Target,Opt>::make_gf_view(std::forward<U>(x)...);}
template<typename Variable, typename Target, typename Opt> struct gf_desc{};
template<typename Descriptor> struct gf_tag{};
// The trait that "marks" the Green function
TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableGreenFunction);
@ -89,28 +93,31 @@ namespace triqs { namespace gfs {
/// A common implementation class for gf and gf_view. They will only redefine contructor and = ...
template<typename Variable, typename Target, typename Opt, bool IsView> class gf_impl :
TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction), gf_tag<gf_desc<Variable,Target,Opt>> {
public :
// Pattern : ValueView
typedef gf_view<Variable,Target,Opt> view_type;
typedef gf<Variable,Target,Opt> regular_type;
typedef gf_desc<Variable,Target,Opt> descriptor_t;
typedef Variable variable_t;
typedef Target target_t;
typedef Opt option_t;
typedef gf_mesh<Variable,Opt> mesh_t;
typedef typename mesh_t::domain_t domain_t;
typedef typename mesh_t::mesh_point_t mesh_point_t;
typedef typename mesh_t::index_t mesh_index_t;
typedef typename gfs_implementation::symmetry<Variable,Target,Opt>::type symmetry_t;
typedef gfs_implementation::evaluator<Variable,Target,Opt> evaluator_t;
typedef typename gfs_implementation::symmetry<Variable,Target,Opt>::type symmetry_t;
typedef gfs_implementation::evaluator<Variable,Target,Opt> evaluator_t;
typedef gfs_implementation::data_proxy<Variable,Target,Opt> data_proxy_t;
typedef gfs_implementation::data_proxy<Variable,Target,Opt> data_proxy_t;
typedef typename data_proxy_t::storage_t data_regular_t;
typedef typename data_proxy_t::storage_view_t data_view_t;
typedef typename std::conditional<IsView, data_view_t, data_regular_t>::type data_t;
typedef typename std::conditional<IsView, data_view_t, data_regular_t>::type data_t;
typedef typename gfs_implementation::singularity<Variable,Target,Opt>::type singularity_non_view_t;
typedef typename gfs_implementation::singularity<Variable,Target,Opt>::type singularity_non_view_t;
typedef typename view_type_if_exists_else_type<singularity_non_view_t>::type singularity_view_t;
typedef typename std::conditional<IsView, singularity_view_t, singularity_non_view_t>::type singularity_t;
@ -178,6 +185,13 @@ namespace triqs { namespace gfs {
>::type // end of add_Const
operator() (Arg0&& arg0, Args&&... args) const { return _evaluator(this,std::forward<Arg0>( arg0), std::forward<Args>(args)...); }
// Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression
//template<typename Arg0, typename ...Args>
// auto operator()(Arg0 arg0, Args... args) const DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...));
//template<typename Arg0, typename ...Args>
// auto operator()(Arg0 arg0, Args... args) DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...));
template<typename Arg0, typename ...Args>
typename clef::_result_of::make_expr_call<view_type,Arg0, Args...>::type
operator()(Arg0 arg0, Args... args) const {
@ -213,14 +227,34 @@ namespace triqs { namespace gfs {
template<typename ... U>
cr_type operator[] (closest_pt_wrap<U...> const & p) const { return _data_proxy(_data, _mesh.index_to_linear( gfs_implementation::get_closest_point<Variable,Target,Opt>::invoke(this,p)));}
// Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression
/* template<typename Arg>
typename boost::lazy_enable_if< // enable the template if
clef::is_any_lazy<Arg>, // One of Args is a lazy expression
clef::_result_of::make_expr_subscript<view_type,Arg>
>::type // end of lazy_enable_if
operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg));}
*/
/*template<typename Arg>
//auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward<Arg>(arg)));
auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg)));
template<typename Arg>
//auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward<Arg>(arg)));
auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg)));
*/
template<typename Arg>
typename clef::_result_of::make_expr_subscript<view_type,Arg>::type
operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg));}
/// A direct access to the grid point
template<typename... Args>
r_type on_mesh (Args&&... args) { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));}
/// A direct access to the grid point (const version)
template<typename... Args>
cr_type on_mesh (Args&&... args) const { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));}
@ -245,7 +279,7 @@ namespace triqs { namespace gfs {
friend void h5_write (h5::group fg, std::string subgroup_name, gf_impl const & g) {
auto gr = fg.create_group(subgroup_name);
gr.write_triqs_hdf5_data_scheme(g);
gfs_implementation::h5_ops<Variable,Target,Opt>::write(gr, "data", g._data, g);
gfs_implementation::h5_ops<Variable,Target,Opt>::write(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks)
h5_write(gr,"singularity",g._singularity);
h5_write(gr,"mesh",g._mesh);
h5_write(gr,"symmetry",g._symmetry);
@ -259,7 +293,7 @@ namespace triqs { namespace gfs {
auto tag_expected= get_triqs_hdf5_data_scheme(g);
if (tag_file != tag_expected)
TRIQS_RUNTIME_ERROR<< "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found "<<tag_file << " while I expected "<< tag_expected;
gfs_implementation::h5_ops<Variable,Target,Opt>::read(gr, "data", g._data, g);
gfs_implementation::h5_ops<Variable,Target,Opt>::read(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks)
h5_read(gr,"singularity",g._singularity);
h5_read(gr,"mesh",g._mesh);
h5_read(gr,"symmetry",g._symmetry);
@ -303,13 +337,13 @@ namespace triqs { namespace gfs {
friend void swap (gf & a, gf & b) noexcept { a.swap_impl (b);}
gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move =
gf & operator = (gf & rhs) { *this = gf(rhs); return *this;} // use move =
gf & operator = (gf && rhs) noexcept { swap(*this,rhs); return *this;}
gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move =
gf & operator = (gf & rhs) { *this = gf(rhs); return *this;} // use move =
gf & operator = (gf && rhs) noexcept { swap(*this, rhs); return *this;}
template<typename RHS> void operator = (RHS && rhs) {
this->_mesh = std::forward<RHS>(rhs).mesh();
for (auto const & w: this->mesh()) (*this)[w] = rhs[w];
this->_mesh = rhs.mesh();
B::data_proxy_t::assign_with_resize(this->data(), std::forward<RHS>(rhs).data()); // looks strange for &&
this->_singularity = rhs.singularity();
// to be implemented : there is none in the gf_expr in particular....
//this->_symmetry = rhs.symmetry();
@ -371,8 +405,8 @@ namespace triqs { namespace gfs {
// delegate = so that I can overload it for specific RHS...
template<typename Variable, typename Target, typename Opt, typename RHS>
DISABLE_IF(arrays::is_scalar<RHS>) triqs_gf_view_assign_delegation( gf_view<Variable,Target,Opt> g, RHS const & rhs) {
if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh";
for (auto const & w: g.mesh()) g[w] = rhs[w];
if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh";
gf_view<Variable,Target,Opt>::data_proxy_t::assign_no_resize(g.data(),rhs.data());
g.singularity() = rhs.singularity();
}

View File

@ -21,93 +21,93 @@
#ifndef TRIQS_GF_EXPR_H
#define TRIQS_GF_EXPR_H
#include <triqs/utility/expression_template_tools.hpp>
namespace triqs { namespace gfs {
namespace triqs { namespace gfs {
using utility::is_in_ZRC;
using utility::remove_rvalue_ref;
namespace gfs_expr_tools {
// a wrapper for scalars
namespace gfs_expr_tools {
template<typename S> struct scalar_wrap {
typedef void variable_t;
typedef void target_t;
typedef void option_t;
S s;
template<typename T> scalar_wrap(T && x):s(std::forward<T>(x)){}
typedef S value_type;
S s; scalar_wrap(S const &s_):s(s_){}
S singularity() const { return s;}
template<typename KeyType> S operator[](KeyType && key) const { return s;}
template<typename ... Args> inline S operator()(Args && ... args) const { return s;}
S data() const { return s;}
template<typename KeyType> value_type operator[](KeyType && key) const { return s;}
template<typename ... Args> inline value_type operator()(Args && ... args) const { return s;}
friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; }
};
// Combine the two meshes of LHS and RHS : need to specialize where there is a scalar
struct combine_mesh {
template<typename L, typename R>
auto operator() (L && l, R && r) const -> decltype(std::forward<L>(l).mesh()) {
inline auto operator() (L const & l, R const & r) const -> decltype(l.mesh()) {
if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : ";//<< l.mesh()<<" vs" <<r.mesh();
return std::forward<L>(l).mesh();
return l.mesh();
}
template<typename S, typename R> auto operator() (scalar_wrap<S> const &, R && r) const DECL_AND_RETURN(std::forward<R>(r).mesh());
template<typename S, typename L> auto operator() (L && l, scalar_wrap<S> const &) const DECL_AND_RETURN(std::forward<L>(l).mesh());
template<typename S, typename R> auto operator() (scalar_wrap<S> const & w, R const & r) const -> decltype(r.mesh()) { return r.mesh();}
template<typename S, typename L> auto operator() (L const & l, scalar_wrap<S> const & w) const -> decltype(l.mesh()) { return l.mesh();}
};
template<typename T> struct node_t : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, typename remove_rvalue_ref<T>::type> {};
template <typename A, typename B> struct _or_ {typedef void type;};
template <typename A> struct _or_<A,A> {typedef A type;};
template <typename A> struct _or_<void,A> {typedef A type;};
template <typename A> struct _or_<A,void> {typedef A type;};
template <> struct _or_<void,void> {typedef void type;};
template<typename T> struct keeper_type : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, typename view_type_if_exists_else_type<T>::type> {};
}// gfs_expr_tools
template<typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename std::remove_reference<L>::type L_t;
typedef typename std::remove_reference<R>::type R_t;
typedef typename gfs_expr_tools::_or_<typename L_t::variable_t,typename R_t::variable_t>::type variable_t;
typedef typename gfs_expr_tools::_or_<typename L_t::target_t,typename R_t::target_t>::type target_t;
typedef typename gfs_expr_tools::_or_<typename L_t::option_t,typename R_t::option_t>::type option_t;
static_assert(!std::is_same<variable_t,void>::value, "Can not combine two gf expressions with different variables");
static_assert(!std::is_same<target_t,void>::value, "Can not combine two gf expressions with different target");
L l; R r;
template<typename LL, typename RR> gf_expr(LL && l_, RR && r_):l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
auto mesh() const DECL_AND_RETURN(gfs_expr_tools::combine_mesh()(l,r));
template<typename Descriptor, typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor> {
typedef typename gfs_expr_tools::keeper_type<L>::type L_t;
typedef typename gfs_expr_tools::keeper_type<R>::type R_t;
typedef Descriptor descriptor_t;
//typedef typename std::result_of<utility::operation<Tag>(typename L_t::value_type,typename R_t::value_type)>::type value_t;
typedef typename std::remove_reference<typename std::result_of<gfs_expr_tools::combine_mesh(L_t,R_t)>::type>::type mesh_t;
//typedef typename Descriptor::singularity_t::view_type singularity_view_t;
//typedef value_t value_type;
L_t l; R_t r;
template<typename LL, typename RR> gf_expr(LL && l_, RR && r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
mesh_t mesh() const { return gfs_expr_tools::combine_mesh()(l,r); }
auto data() const ->decltype( utility::operation<Tag>()(l.data(), r.data())) { return utility::operation<Tag>()(l.data(), r.data());}
auto singularity() const DECL_AND_RETURN (utility::operation<Tag>()(l.singularity() , r.singularity()));
template<typename KeyType> auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation<Tag>()(l[std::forward<KeyType>(key)] , r[std::forward<KeyType>(key)]));
//const singularity_view_t singularity() const { return utility::operation<Tag>()(l.singularity() , r.singularity());}
//symmetry_t const & symmetry() const { return _symmetry;}
template<typename KeyType> auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation<Tag>()(l[std::forward<KeyType>(key)] , r[std::forward<KeyType>(key)]));
template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation<Tag>()(l(std::forward<Args>(args)...) , r(std::forward<Args>(args)...)));
friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<<expr.l << " "<<utility::operation<Tag>::name << " "<<expr.r<<")" ; }
};
// -------------------------------------------------------------------
//a special case : the unary operator !
template<typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename std::remove_reference<L>::type L_t;
typedef typename L_t::variable_t variable_t;
typedef typename L_t::target_t target_t;
typedef typename L_t::option_t option_t;
L l;
template<typename Descriptor, typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor>{
typedef typename gfs_expr_tools::keeper_type<L>::type L_t;
typedef Descriptor descriptor_t;
//typedef typename L_t::value_type value_type;
typedef typename L_t::mesh_t mesh_t;
//typedef typename Descriptor::singularity_t::view_type singularity_view_t;
L_t l;
template<typename LL> gf_unary_m_expr(LL && l_) : l(std::forward<LL>(l_)) {}
auto mesh() const DECL_AND_RETURN(l.mesh());
mesh_t mesh() const { return l.mesh(); }
auto data() const ->decltype( - l.data()) { return - l.data();}
auto singularity() const DECL_AND_RETURN(l.singularity());
//const singularity_view_t singularity() const { return l.singularity();}
//symmetry_t const & symmetry() const { return _symmetry;}
template<typename KeyType> auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]);
template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward<Args>(args)...));
friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'<<expr.l; }
};
// -------------------------------------------------------------------
// get the descriptor ...
template<typename A1, typename A2, typename Enable=void> struct get_desc;
template<typename A1, typename A2>
struct get_desc <A1,A2, typename std::enable_if<((!ImmutableGreenFunction<A1>::value) && (ImmutableGreenFunction<A2>::value))>::type > {
typedef typename A2::descriptor_t type;
};
template<typename A1, typename A2>
struct get_desc <A1,A2,typename std::enable_if<(!ImmutableGreenFunction<A2>::value) && (ImmutableGreenFunction<A1>::value)>::type > {
typedef typename A1::descriptor_t type;
};
template<typename A1, typename A2>
struct get_desc <A1,A2, typename std::enable_if< (ImmutableGreenFunction<A1>::value) && (ImmutableGreenFunction<A2>::value) && std::is_same<typename A1::descriptor_t,typename A2::descriptor_t>::value >::type > { typedef typename A2::descriptor_t type; };
// -------------------------------------------------------------------
// Now we can define all the C++ operators ...
#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
template<typename A1, typename A2>\
typename std::enable_if<TRAIT1<A1>::value && TRAIT2 <A2>::value, \
gf_expr<utility::tags::TAG, typename gfs_expr_tools::node_t<A1>::type, typename gfs_expr_tools::node_t<A2>::type>>::type\
operator OP (A1 && a1, A2 && a2) { return {std::forward<A1>(a1),std::forward<A2>(a2)};}
typename std::enable_if<TRAIT1<A1>::value && TRAIT2 <A2>::value, gf_expr<typename get_desc<A1,A2>::type, utility::tags::TAG, A1,A2>>::type\
operator OP (A1 const & a1, A2 const & a2) { return gf_expr<typename get_desc<A1,A2>::type,utility::tags::TAG, A1,A2>(a1,a2);}
DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction);
DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction);
@ -120,12 +120,8 @@ namespace triqs { namespace gfs {
#undef DEFINE_OPERATOR
// the unary is special
template<typename A1>
typename std::enable_if<
ImmutableGreenFunction<A1>::value,
gf_unary_m_expr<typename gfs_expr_tools::node_t<A1>::type >
>::type
operator - (A1 && a1) { return {std::forward<A1>(a1)};}
template<typename A1> typename std::enable_if<ImmutableGreenFunction<A1>::value, gf_unary_m_expr<typename A1::descriptor_t, A1>>::type
operator - (A1 const & a1) { return gf_unary_m_expr<typename A1::descriptor_t, A1>(a1);}
}}//namespace triqs::gf
#endif