proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
ArgumentsDict.h
Go to the documentation of this file.
1#ifndef ARGUMENTSDICT_H
2#define ARGUMENTSDICT_H
3
4#include <map>
5#include <stdexcept>
6#include <string>
7#include "xtensor-python/pyarray.hpp"
8#include "xtensor/io/xio.hpp"
9
10namespace proteus
11{
12
13 /****************
14 * throwing_map *
15 ****************/
16
17 // Special map that behaves like a standard map except for
18 // - operator[] which throws instead of inserting a default
19 // value when a key is not found
20 // - insert and insert_or_assign which always move the key
21 // and the value. This allows to keep pyarrays synchronized
22 // with the numpy arrays they refer to, while avoiding code
23 // duplication for array of scalars (because insert_or_assign
24 // is not available in C++14)
25 template <class K, class T>
26 class throwing_map : private std::map<K, T>
27 {
28 public:
29
30 using base_type = std::map<K, T>;
31 using key_type = typename base_type::key_type;
32 using mapped_type = typename base_type::mapped_type;
33 using value_type = typename base_type::value_type;
34 using reference = typename base_type::reference;
35 using const_reference = typename base_type::const_reference;
36 using pointer = typename base_type::pointer;
37 using const_pointer = typename base_type::const_pointer;
38 using size_type = typename base_type::size_type;
39 using difference_type = typename base_type::difference_type;
40 using iterator = typename base_type::iterator;
41 using const_iterator = typename base_type::const_iterator;
42
43 using base_type::empty;
44 using base_type::find;
45 using base_type::emplace;
46
47 using base_type::begin;
48 using base_type::end;
49 using base_type::cbegin;
50 using base_type::cend;
51
52 // Throws if k is not in the map
54
55 std::pair<iterator, bool> insert(value_type&&);
56 std::pair<iterator, bool> insert_or_assign(key_type&& k, mapped_type&& v);
57 };
58
59 /******************
60 * arguments_dict *
61 ******************/
62
63 template <class K, class T>
65
66 template <class K, class T>
68
70 {
75
76 template <class T>
77 xt::pyarray<T>& array(const std::string& key);
78
79 template <class T>
80 T& scalar(const std::string& key);
81
82 private:
83
84 template <class D1, class D2>
85 typename D1::mapped_type& find_element(const std::string& key,
86 D1& expected_dict,
87 const D2& other_dict,
88 const std::string& expected_type,
89 const std::string& other_type);
90
91 template <class D>
92 std::string get_additional_error_msg(const std::string& key,
93 const D& d,
94 const std::string& asked_type,
95 const std::string& tried_type) const;
96 };
97
98 /*******************************
99 * throwing_map implementation *
100 *******************************/
101
102 namespace detail
103 {
104 template <class T>
105 inline std::string key_error_messagei(const T& key)
106 {
107 return key_error_message(std::to_string(key));
108 }
109
110 inline std::string key_error_message(const std::string& key)
111 {
112 return std::string("key ") + key + std::string(" not found");
113 }
114 }
115
116 template <class K, class T>
118 {
119 auto it = this->find(k);
120 if(it == end())
121 {
122 throw std::runtime_error(detail::key_error_message(k));
123 }
124 return it->second;
125 }
126
127 template <class K, class T>
128 inline auto throwing_map<K, T>::insert(value_type&& v) -> std::pair<iterator, bool>
129 {
130 return base_type::insert(std::move(v));
131 }
132
133 template <class K, class T>
134 inline auto throwing_map<K, T>::insert_or_assign(key_type&& k, mapped_type&& v) -> std::pair<iterator, bool>
135 {
136 auto it = base_type::find(k);
137 if(it == base_type::end())
138 {
139 return base_type::emplace(k, std::move(v));
140 }
141 else
142 {
143 it->second = std::move(v);
144 return std::make_pair(it, false);
145 }
146 }
147
148 /*********************************
149 * arguments_dict implementation *
150 *********************************/
151
152 template <>
153 inline xt::pyarray<double>& arguments_dict::array<double>(const std::string& key)
154 {
155 return find_element(key, m_darray, m_iarray, "pyarray<double>", "pyarray<int>");
156 }
157
158 template <>
159 inline xt::pyarray<int>& arguments_dict::array<int>(const std::string& key)
160 {
161 return find_element(key, m_iarray, m_darray, "pyarray<int>", "pyarray<double>");
162 }
163
164 template <>
165 inline double& arguments_dict::scalar<double>(const std::string& key)
166 {
167 return find_element(key, m_dscalar, m_iscalar, "double scalar", "int scalar");
168 }
169
170 template <>
171 inline int& arguments_dict::scalar<int>(const std::string& key)
172 {
173 return find_element(key, m_iscalar, m_dscalar, "int scalar", "double scalar");
174 }
175
176 template <class D1, class D2>
177 typename D1::mapped_type& arguments_dict::find_element(const std::string& key,
178 D1& expected_dict,
179 const D2& other_dict,
180 const std::string& expected_type,
181 const std::string& other_type)
182 {
183 try
184 {
185 return expected_dict[key];
186 }
187 catch(std::runtime_error& e)
188 {
189 throw std::runtime_error(e.what()
190 + get_additional_error_msg(key, other_dict, expected_type, other_type));
191 }
192 }
193
194 template <class D>
195 std::string arguments_dict::get_additional_error_msg(const std::string& key,
196 const D& d,
197 const std::string& asked_type,
198 const std::string& tried_type) const
199 {
200 auto it = d.find(key);
201 if (it == d.cend())
202 {
203 return " in any of the internal dicts";
204 }
205 else
206 {
207 return " in dict of " + asked_type + " but found in dict of " + tried_type;
208 }
209 }
210}
211
212#endif
213
Double T
Definition Headers.h:87
Double v
Definition Headers.h:95
std::pair< iterator, bool > insert_or_assign(key_type &&k, mapped_type &&v)
typename base_type::value_type value_type
std::map< K, T > base_type
typename base_type::iterator iterator
typename base_type::mapped_type mapped_type
typename base_type::pointer pointer
mapped_type & operator[](const key_type &k)
typename base_type::const_pointer const_pointer
typename base_type::const_iterator const_iterator
typename base_type::key_type key_type
typename base_type::difference_type difference_type
typename base_type::reference reference
typename base_type::size_type size_type
typename base_type::const_reference const_reference
std::pair< iterator, bool > insert(value_type &&)
#define D(x, y)
Definition jf.h:9
std::string key_error_messagei(const T &key)
std::string key_error_message(const std::string &key)
Definition ADR.h:19
throwing_map< K, T > scalar_dict
throwing_map< K, xt::pyarray< T > > pyarray_dict
T & scalar(const std::string &key)
pyarray_dict< std::string, double > m_darray
scalar_dict< std::string, int > m_iscalar
xt::pyarray< T > & array(const std::string &key)
pyarray_dict< std::string, int > m_iarray
scalar_dict< std::string, double > m_dscalar