14 #include <boost/type_index.hpp> 15 #include <boost/integer_traits.hpp> 17 #include <boost/static_assert.hpp> 19 #include <type_traits> 51 template <
bool V>
struct yes_no {};
52 template <>
struct yes_no<true> :
public std::true_type {
typedef bool yes; };
53 template <>
struct yes_no<false> :
public std::false_type {
typedef bool no; };
56 struct is_bool :
public yes_no<std::is_same<T,bool>::value> {};
60 struct is_integral :
public yes_no<std::is_integral<T>::value && !is_bool<T>::value> {};
65 struct is_allowed :
public yes_no<
67 || std::is_same<char*, T>::value
68 || std::is_same<const char*, T>::value
69 || is_integral<T>::value
70 || is_supported<T>::value> {};
74 struct is_signed :
public yes_no<std::is_signed<T>::value && is_integral<T>::value> {};
78 struct is_unsigned :
public yes_no<std::is_unsigned<T>::value && is_integral<T>::value> {};
81 template <
typename FROM,
typename TO>
82 struct is_bool_to_integral
83 :
public yes_no<is_bool<FROM>::value && is_integral<TO>::value>
87 template <
typename FROM,
typename TO>
88 struct is_sig_to_intgl
89 :
public yes_no<is_signed<FROM>::value && is_integral<TO>::value>
93 template <
typename FROM,
typename TO>
94 struct is_unsig_to_intgl
95 :
public yes_no<is_unsigned<FROM>::value && is_integral<TO>::value>
99 template <
typename FROM,
typename TO>
100 struct is_intgl_to_fp
101 :
public yes_no<is_integral<FROM>::value && std::is_floating_point<TO>::value>
105 template <
typename FROM,
typename TO>
106 struct is_other_conversion
107 :
public yes_no<!is_bool_to_integral<FROM,TO>::value &&
108 !is_sig_to_intgl<FROM,TO>::value &&
109 !is_unsig_to_intgl<FROM,TO>::value &&
110 !is_intgl_to_fp<FROM,TO>::value
115 template <
typename A,
typename B>
116 struct is_both_unsigned
117 :
public yes_no<is_unsigned<A>::value && is_unsigned<B>::value>
121 template <
typename A,
typename B>
122 struct is_both_signed
123 :
public yes_no<is_signed<A>::value && is_signed<B>::value>
127 template <
typename A,
typename B>
128 struct is_signed_unsigned
129 :
public yes_no<is_signed<A>::value && is_unsigned<B>::value>
133 template <
typename A,
typename B>
134 struct is_either_bool
135 :
public yes_no< (is_bool<A>::value && !is_bool<B>::value) ||
136 (!is_bool<A>::value && is_bool<B>::value) >
140 template <
typename A,
typename B>
142 :
public yes_no< std::is_floating_point<A>::value &&
143 std::is_floating_point<B>::value &&
144 !std::is_same<A,B>::value>
148 template <
typename A,
typename B>
150 :
public yes_no<!is_either_bool<A,B>::value &&
151 !is_both_signed<A,B>::value && !is_both_unsigned<A,B>::value &&
152 !is_signed_unsigned<A,B>::value && !is_signed_unsigned<B,A>::value &&
153 !is_intgl_to_fp<A,B>::value && !is_intgl_to_fp<B,A>::value &&
154 !is_fp_conv<A,B>::value>
161 template <
typename T>
163 static std::string pretty_name() {
164 return boost::typeindex::type_id<T>().pretty_name();
170 template <
typename LHS_T>
171 struct getter:
public boost::static_visitor<LHS_T> {
174 LHS_T apply(
const LHS_T& val)
const {
179 template <
typename RHS_T>
180 LHS_T apply(
const RHS_T& val,
typename is_bool_to_integral<RHS_T,LHS_T>::yes =
true)
const {
185 template <
typename RHS_T>
186 LHS_T apply(
const RHS_T& val,
typename is_intgl_to_fp<RHS_T,LHS_T>::yes =
true)
const {
191 template <
typename RHS_T>
192 LHS_T apply(
const RHS_T& val,
typename is_unsig_to_intgl<RHS_T,LHS_T>::yes =
true)
const {
193 typedef typename std::make_unsigned<LHS_T>::type U_LHS_T;
194 const U_LHS_T max_num=boost::integer_traits<LHS_T>::const_max;
197 throw exception::value_mismatch(
"",
"Integer overflow detected: unsigned integer too large");
202 template <
typename RHS_T>
203 LHS_T apply(
const RHS_T& val,
typename is_sig_to_intgl<RHS_T,LHS_T>::yes =
true)
const {
204 typedef typename std::make_signed<LHS_T>::type S_LHS_T;
205 typedef typename std::make_unsigned<LHS_T>::type U_LHS_T;
206 typedef typename std::make_unsigned<RHS_T>::type U_RHS_T;
208 const S_LHS_T min_num=boost::integer_traits<LHS_T>::const_min;
211 throw exception::value_mismatch(
"",
"Integer underflow detected: signed integer too small");
213 if (val<0)
return val;
215 const U_LHS_T max_num=boost::integer_traits<LHS_T>::const_max;
216 const U_RHS_T uval=val;
219 throw exception::value_mismatch(
"",
"Integer overflow detected: signed integer too large");
224 template <
typename RHS_T>
225 LHS_T apply(
const RHS_T& val,
typename is_other_conversion<RHS_T,LHS_T>::yes =
true)
const {
226 std::string rhs_name=detail::type_info<RHS_T>::pretty_name();
227 std::string lhs_name=detail::type_info<LHS_T>::pretty_name();
228 throw exception::type_mismatch(
"",
"Types do not match;" 229 " conversion " + rhs_name +
" --> " + lhs_name);
234 template <
typename RHS_T>
235 LHS_T operator()(
const RHS_T& val)
const {
242 struct getter<bool>:
public boost::static_visitor<bool> {
245 bool apply(
const bool& val)
const {
250 template <
typename RHS_T>
251 bool apply(
const RHS_T& val)
const {
252 std::string rhs_name=detail::type_info<RHS_T>::pretty_name();
253 throw exception::type_mismatch(
"",
"Cannot convert non-bool type "+rhs_name+
" to bool");
257 template <
typename RHS_T>
258 bool operator()(
const RHS_T& val)
const {
264 template <
typename X>
265 class check_type :
public boost::static_visitor<bool> {
268 bool operator()(
const X& val)
const {
return true; }
271 template <
typename T>
272 bool operator()(
const T& val)
const {
return false; }
277 template <
typename RHS_T>
278 class comparator :
public boost::static_visitor<int> {
281 template <
typename A,
typename B>
282 static bool cmp_(
const A& a,
const B& b) {
return (a==b)? 0 : (a<b)? -1:1; }
285 comparator(
const RHS_T& rhs): rhs_(rhs) {}
288 int operator()(
const RHS_T& lhs)
const {
289 return cmp_(lhs,rhs_);
293 template <
typename LHS_T>
294 int operator()(
const LHS_T& lhs)
const {
295 return apply(lhs,rhs_);
299 template <
typename LHS_T>
300 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
301 typename is_either_bool<LHS_T,RHS_T>::yes =
true)
const {
302 std::string lhs_name=detail::type_info<LHS_T>::pretty_name();
303 std::string rhs_name=detail::type_info<RHS_T>::pretty_name();
304 throw exception::type_mismatch(
"",
"Attempt to compare a boolean value with an incompatible type "+
305 lhs_name +
"<=>" + rhs_name);
309 template <
typename LHS_T>
310 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_both_signed<LHS_T,RHS_T>::yes =
true)
const {
311 return cmp_(lhs,rhs);
315 template <
typename LHS_T>
316 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_both_unsigned<LHS_T,RHS_T>::yes =
true)
const {
317 return cmp_(lhs,rhs);
321 template <
typename LHS_T>
322 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_signed_unsigned<LHS_T,RHS_T>::yes =
true)
const {
323 typedef typename std::make_unsigned<LHS_T>::type U_LHS_T;
324 if (lhs<0)
return -1;
326 U_LHS_T u_lhs=
static_cast<U_LHS_T
>(lhs);
327 return cmp_(u_lhs, rhs);
331 template <
typename LHS_T>
332 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_signed_unsigned<RHS_T,LHS_T>::yes =
true)
const {
333 return -apply(rhs,lhs);
337 template <
typename LHS_T>
338 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_intgl_to_fp<LHS_T,RHS_T>::yes =
true)
const {
339 return cmp_(lhs, rhs);
343 template <
typename LHS_T>
344 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_intgl_to_fp<RHS_T,LHS_T>::yes =
true)
const {
345 return cmp_(lhs, rhs);
349 template <
typename LHS_T>
350 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_fp_conv<RHS_T,LHS_T>::yes =
true)
const {
351 return cmp_(lhs, rhs);
355 template <
typename LHS_T>
356 int apply(
const LHS_T& lhs,
const RHS_T& rhs,
typename is_other_cmp<LHS_T,RHS_T>::yes =
true)
const {
357 std::string lhs_name=detail::type_info<LHS_T>::pretty_name();
358 std::string rhs_name=detail::type_info<RHS_T>::pretty_name();
359 throw exception::type_mismatch(
"",
"Attempt to compare incompatible types "+
360 lhs_name +
"<=>" + rhs_name);
367 template <
typename F>
372 template <
typename F>
378 return val_.which()==0;
381 template <
typename X>
386 template <
typename T>
393 val_=std::string(rhs);
397 template <
typename T>
399 BOOST_STATIC_ASSERT_MSG(detail::is_allowed<T>::value,
"The type is not supported by dictionary");
418 template <
typename T>
421 BOOST_STATIC_ASSERT_MSG(detail::is_allowed<T>::value,
"The type is not supported by dictionary");
437 template <
typename F>
449 template <
typename F>
455 template <
typename T>
464 template <
typename T>
473 template <
typename T>
482 template <
typename T>
534 val.broadcast(comm, root);
void set_name(const std::string &name)
F::result_type apply_visitor(const F &visitor, const dict_value &dv)
Const-access visitor to the bound value.
void broadcast(C const &c, P &p, int r=0)
const T & operator=(const T &rhs)
Assignment operator (with conversion)
bool operator==(const dictionary &lhs, const dictionary &rhs)
Exception for using uninitialized value.
Encapsulation of an MPI communicator and some communicator-related operations.
F::result_type apply_visitor(F &visitor, dictionary::const_iterator it)
Const-access visitor to a value by an iterator.
bool isType() const
check the type of the containing value
void clear()
Reset to an empty value.
bool empty() const
whether the value contains None
T as() const
Shortcut for explicit conversion to a target type.
General exception (base class)
detail::None None
"Empty value" type
bool operator!=(const dictionary &lhs, const dictionary &rhs)
F::result_type apply_visitor(F &visitor) const
Const-access visitor to the bound value.
int compare(const T &rhs) const
Comparison.