ALPSCore reference
dict_value.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
10 #include <boost/version.hpp>
11 
14 
15 #ifdef ALPS_HAVE_MPI
17 #endif
18 
19 namespace alps {
20  namespace params_ns {
21 
22  namespace detail {
23  namespace visitor {
24 
26 
27  class comparator2 : public boost::static_visitor<int> {
28  template <typename A, typename B>
29  static bool cmp_(const A& a, const B& b) { return (a==b)? 0 : (a<b)? -1:1; }
30 
31  public:
33  template <typename LHS_T, typename RHS_T>
34  int operator()(const LHS_T& lhs, const RHS_T& rhs) const {
35  std::string lhs_name=detail::type_info<LHS_T>::pretty_name();
36  std::string rhs_name=detail::type_info<RHS_T>::pretty_name();
37  throw exception::type_mismatch("","Attempt to compare dictionary values containing "
38  "incompatible types "+
39  lhs_name + "<=>" + rhs_name);
40  }
41 
43  template <typename LHS_RHS_T>
44  int operator()(const LHS_RHS_T& lhs, const LHS_RHS_T& rhs) const {
45  return cmp_(lhs,rhs);
46  }
47 
49  int operator()(const dict_value::None& lhs, const dict_value::None& rhs) const {
50  return 1;
51  }
52 
53 
54  // FIXME:TODO:
55  // Same types: compare directly
56  // Integral types: compare using signs (extract it to a separate namespace/class)
57  // FP types: compare directly
58  // Everything else: throw
59  };
60 
62  class equals2 : public boost::static_visitor<bool> {
63  public:
65  template <typename LHS_RHS_T>
66  bool operator()(const LHS_RHS_T& lhs, const LHS_RHS_T& rhs) const {
67  return lhs==rhs;
68  }
69 
71  template <typename LHS_T, typename RHS_T>
72  bool operator()(const LHS_T& lhs, const RHS_T& rhs) const{
73  return false;
74  }
75 
77  template <typename RHS_T>
78  bool operator()(const dict_value::None&, const RHS_T&) const {
79  return false;
80  }
81 
83  template <typename LHS_T>
84  bool operator()(const LHS_T&, const dict_value::None&) const {
85  return false;
86  }
87 
89  bool operator()(const dict_value::None&, const dict_value::None&) const {
90  return true;
91  }
92  };
93 
94  } // visitor::
95 
96  } // detail::
97 
98  int dict_value::compare(const dict_value& rhs) const
99  {
100  if (this->empty() || rhs.empty()) throw exception::uninitialized_value(name_+"<=>"+rhs.name_,"Attempt to compare uninitialized value");
101 
102  try {
103  return boost::apply_visitor(detail::visitor::comparator2(), val_, rhs.val_);
104  } catch (exception::exception_base& exc) {
105  exc.set_name(name_+"<=>"+rhs.name_);
106  throw;
107  }
108  }
109 
110  bool dict_value::equals(const dict_value& rhs) const
111  {
112  return boost::apply_visitor(detail::visitor::equals2(), val_, rhs.val_);
113  }
114 
116  if (this->empty()) return;
117  alps::hdf5::write_variant<detail::dict_all_types>(ar, val_);
118  }
119 
121  const std::string context=ar.get_context();
122  std::string::size_type slash_pos=context.find_last_of("/");
123  if (slash_pos==std::string::npos) slash_pos=0; else ++slash_pos;
124  name_=context.substr(slash_pos);
125  val_=alps::hdf5::read_variant<detail::dict_all_types>(ar);
126  }
127 
128  namespace {
129  struct typestring_visitor : public boost::static_visitor<std::string> {
130  template <typename T>
131  std::string operator()(const T& val) const {
132  std::string ret=detail::type_info<T>::pretty_name();
133  return ret;
134  }
135  };
136 
137  // Printing of a vector
138  // FIXME!!! Consolidate with other definitions and move to alps::utilities
139  template <typename T>
140  inline std::ostream& operator<<(std::ostream& strm, const std::vector<T>& vec)
141  {
142  typedef std::vector<T> vtype;
143  typedef typename vtype::const_iterator itype;
144 
145  strm << "[";
146  itype it=vec.begin();
147  const itype end=vec.end();
148 
149  if (end!=it) {
150  strm << *it;
151  for (++it; end!=it; ++it) {
152  strm << ", " << *it;
153  }
154  }
155  strm << "]";
156 
157  return strm;
158  }
159 
160  struct print_visitor {
161 #if __cplusplus == 201402L && BOOST_VERSION == 105800
162  // Workaround for a bug in boost 1.58 with C++14.
163  // Defining `result_type` as a reference type
164  // leads to a compilation error;
165  // however, C++14 is able to deduce the type of the result
166  // without `result_type` being defined.
167 #else
168  typedef std::ostream& result_type;
169 #endif
170  std::ostream& os_;
171 
172  print_visitor(std::ostream& os) : os_(os) {}
173 
174  template <typename T>
175  std::ostream& operator()(const T& val) const {
176  return os_ << val;
177  }
178 
179  std::ostream& operator()(const dict_value::None&) const {
180  throw std::logic_error("print_visitor: This is not expected to be called");
181  }
182  };
183 
184  }
185 
186  std::ostream& print(std::ostream& s, const dict_value& dv, bool terse) {
187  if (dv.empty()) {
188  s << "[NONE]";
189  if (!terse) s << " (type: None)";
190  } else {
191  // s << dv.val_;
192  boost::apply_visitor(print_visitor(s), dv.val_);
193  if (!terse) s << " (type: " << boost::apply_visitor(typestring_visitor(), dv.val_) << ")";
194  }
195  if (!terse) s << " (name='" << dv.name_ << "')";
196  return s;
197  }
198 
199 #ifdef ALPS_HAVE_MPI
200  void dict_value::broadcast(const alps::mpi::communicator& comm, int root)
201  {
202  using alps::mpi::broadcast;
203  broadcast(comm, name_, root);
204  broadcast<detail::dict_all_types>(comm, val_, root);
205  }
206 #endif
207 
208 
209  } // params_ns::
210 } // alps::
void set_name(const std::string &name)
std::ostream & os_
Definition: dict_value.cpp:170
void broadcast(C const &c, P &p, int r=0)
Definition: api.hpp:56
void save(alps::hdf5::archive &ar) const
Saves the value to an archive.
Definition: dict_value.cpp:115
Exception for using uninitialized value.
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
F::result_type apply_visitor(F &visitor, dictionary::const_iterator it)
Const-access visitor to a value by an iterator.
Definition: dictionary.hpp:110
bool equals(const dict_value &rhs) const
Returns true if the objects hold the same type and value, false otherwise.
Definition: dict_value.cpp:110
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
Definition: dict_value.cpp:186
bool empty() const
whether the value contains None
std::string get_context() const
Definition: archive.cpp:144
Header for archiving interface for boost::variant.
void broadcast(const communicator &comm, T *vals, std::size_t count, int root)
Broadcasts array vals of a primitive type T, length count on communicator comm with root root ...
Definition: mpi.hpp:270
General exception (base class)
void load(alps::hdf5::archive &ar)
Loads the value from an archive.
Definition: dict_value.cpp:120
detail::None None
"Empty value" type
Definition: dict_value.hpp:66
int compare(const T &rhs) const
Comparison.