From 512812605572fdce3fac08e3f5cd9b1160b2fd84 Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Sun, 2 Mar 2014 14:14:59 +0100 Subject: [PATCH] arrays: change operator() && for const_view Changed operator()(int, int...) && for array, and views. - For const_view and regular type, returns value_type (i.e. a copy). NB : does make a copy, not a move. Ok for scalar type. TODO: think for complicated types. This allows codes like : f(x)(0,0) where f : x-> matrix or const_view to be correct in clef expression evaluation. - For _view : return a value_type &, as before to allow : A(....)(0,0) = rhs; It is not possible to detect dangling refs in that case at compile time. Added a security in TRIQS_ARRAYS_DEBUG mode to detect a dangling ref at run time, i.e. the case where the view is "unique" (ref count ==1). This would be a quite bad design anyway ... - also : - clean operator[] for vector (old workaround for old gcc...) - add IsView flag in ISP impl class, for the impl. of operator() && --- triqs/arrays/array.hpp | 4 ++-- triqs/arrays/impl/indexmap_storage_pair.hpp | 26 ++++++++++++++++++--- triqs/arrays/matrix.hpp | 4 ++-- triqs/arrays/storages/mem_block.hpp | 2 ++ triqs/arrays/storages/shared_block.hpp | 2 ++ triqs/arrays/vector.hpp | 19 ++++++--------- triqs/gfs/gf.hpp | 3 +-- 7 files changed, 39 insertions(+), 21 deletions(-) diff --git a/triqs/arrays/array.hpp b/triqs/arrays/array.hpp index f64dc29e..1db3ac36 100644 --- a/triqs/arrays/array.hpp +++ b/triqs/arrays/array.hpp @@ -34,7 +34,7 @@ namespace triqs { namespace arrays { // ---------------------- array_view -------------------------------- #define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map, \ - storages::shared_block, Opt, TraversalOrder, IsConst, Tag::array_view > + storages::shared_block, Opt, TraversalOrder, IsConst, true, Tag::array_view > template class array_view: Tag::array_view, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { @@ -106,7 +106,7 @@ namespace triqs { namespace arrays { //------------------------------- array --------------------------------------------------- #define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map, \ - storages::shared_block, Opt, TraversalOrder, false, Tag::array_view > + storages::shared_block, Opt, TraversalOrder, false, false, Tag::array_view > template class array: Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { diff --git a/triqs/arrays/impl/indexmap_storage_pair.hpp b/triqs/arrays/impl/indexmap_storage_pair.hpp index 5bc3c7a2..8341f117 100644 --- a/triqs/arrays/impl/indexmap_storage_pair.hpp +++ b/triqs/arrays/impl/indexmap_storage_pair.hpp @@ -52,7 +52,7 @@ namespace triqs { namespace arrays { template struct ISPViewType; - template + template class indexmap_storage_pair : Tag::indexmap_storage_pair, TRIQS_CONCEPT_TAG_NAME(MutableCuboidArray) { public : @@ -182,13 +182,33 @@ namespace triqs { namespace arrays { typename std::enable_if< (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank==0) && (!IsConst) , value_type &>::type - operator()(Args const & ... args) { return storage_[indexmap_(args...)]; } + operator()(Args const & ... args) & { return storage_[indexmap_(args...)]; } template typename std::enable_if< (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank==0) , value_type const &>::type - operator()(Args const & ... args) const { return storage_[indexmap_(args...)]; } + operator()(Args const & ... args) const & { return storage_[indexmap_(args...)]; } + + // && : return a & iif it is a non const view + template + typename std::enable_if< + (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank==0) && (!IsConst&&IsView) + , value_type &>::type + operator()(Args const & ... args) && { + // add here a security check in case it is a view, unique. For a regular type, move the result... +#ifdef TRIQS_ARRAYS_DEBUG + if (storage_.is_unique()) TRIQS_RUNTIME_ERROR <<"BUG : array : rvalue ref for an array..."; +#endif + return storage_[indexmap_(args...)]; + } + + // && return a value if this is not a view (regular class) or it is a const_view + template + typename std::enable_if< + (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank==0) && (!(!IsConst&&IsView)) + , value_type>::type + operator()(Args const & ... args) && { return storage_[indexmap_(args...)]; } template struct result_of_call_as_view { typedef typename indexmaps::slicer::r_type IM2; diff --git a/triqs/arrays/matrix.hpp b/triqs/arrays/matrix.hpp index 34d1aeb6..b8f4e0e5 100644 --- a/triqs/arrays/matrix.hpp +++ b/triqs/arrays/matrix.hpp @@ -44,7 +44,7 @@ namespace triqs { namespace arrays { bool memory_layout_is_fortran() const { return this->indexmap().strides()[0] < this->indexmap().strides()[1]; } #define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \ - storages::shared_block, Opt, TraversalOrder, IsConst, Tag::matrix_view > + storages::shared_block, Opt, TraversalOrder, IsConst, true, Tag::matrix_view > template class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { @@ -116,7 +116,7 @@ namespace triqs { namespace arrays { // ---------------------- matrix -------------------------------- #define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \ - storages::shared_block, Opt, TraversalOrder, false, Tag::matrix_view > + storages::shared_block, Opt, TraversalOrder, false, false, Tag::matrix_view > template class matrix: Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { diff --git a/triqs/arrays/storages/mem_block.hpp b/triqs/arrays/storages/mem_block.hpp index 21596830..039194c9 100644 --- a/triqs/arrays/storages/mem_block.hpp +++ b/triqs/arrays/storages/mem_block.hpp @@ -261,6 +261,8 @@ namespace triqs { namespace arrays { namespace storages { //namespace details { size_t size() const {return size_;} + bool is_unique() const { return (ref_count + weak_ref_count) == 1; } + template void save(Archive & ar, const unsigned int version) const { ar << boost::serialization::make_nvp("size",size_); diff --git a/triqs/arrays/storages/shared_block.hpp b/triqs/arrays/storages/shared_block.hpp index a495979e..0fcbb4a4 100644 --- a/triqs/arrays/storages/shared_block.hpp +++ b/triqs/arrays/storages/shared_block.hpp @@ -81,6 +81,8 @@ namespace triqs { namespace arrays { namespace storages { return *this; } + bool is_unique() const { return sptr && sptr->is_unique();} + /// True copy of the data shared_block clone() const { shared_block res; diff --git a/triqs/arrays/vector.hpp b/triqs/arrays/vector.hpp index 74b530d2..bfa6a23f 100644 --- a/triqs/arrays/vector.hpp +++ b/triqs/arrays/vector.hpp @@ -34,7 +34,7 @@ namespace triqs { namespace arrays { // ---------------------- vector_view -------------------------------- -#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block, Opt, 0, IsConst, Tag::vector_view > +#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block, Opt, 0, IsConst, true, Tag::vector_view > /** */ template @@ -97,11 +97,8 @@ namespace triqs { namespace arrays { TRIQS_DEFINE_COMPOUND_OPERATORS(vector_view); // to make interface similar to std::vector : forward [] to () - template typename std::result_of::type operator[](Arg && arg) const { return (*this) (std::forward(arg));} - template typename std::result_of::type operator[](Arg && arg) { return (*this) (std::forward(arg));} - // gcc 4.6 does not like this one... - //template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); - //template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); + template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); + template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); }; #undef IMPL_TYPE @@ -112,7 +109,7 @@ namespace triqs { namespace arrays { using vector_const_view = vector_view; // ---------------------- vector-------------------------------- -#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block, Opt, 0, false,Tag::vector_view > +#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block, Opt, 0, false, false,Tag::vector_view > template class vector: Tag::vector, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE { @@ -206,11 +203,9 @@ namespace triqs { namespace arrays { TRIQS_DEFINE_COMPOUND_OPERATORS(vector); - // to make interface similar to std::vector : forward [] to () - template typename std::result_of::type operator[](Arg && arg) const { return (*this) (std::forward(arg));} - template typename std::result_of::type operator[](Arg && arg) { return (*this) (std::forward(arg));} - //template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); - //template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); + // to make interface similar to std::vector : forward [] to () + template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); + template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); };//vector class }}//namespace triqs::arrays diff --git a/triqs/gfs/gf.hpp b/triqs/gfs/gf.hpp index 9545524a..cb6c6d76 100644 --- a/triqs/gfs/gf.hpp +++ b/triqs/gfs/gf.hpp @@ -202,13 +202,12 @@ namespace gfs { /// Calls are (perfectly) forwarded to the evaluator::operator(), except mesh_point_t and when /// there is at least one lazy argument ... template // match any argument list, picking out the first type : () is not permitted - typename std::add_const::value || ((sizeof...(Args) != evaluator_t::arity) && (evaluator_t::arity != -1)) // if -1 : no check , std::result_of // what is the result type of call >::type // end of lazy_disable_if - >::type // end of add_Const operator()(Args &&... args) const { return _evaluator(this, std::forward(args)...); }