ALPSCore reference
cast.hpp
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 
7 #ifndef ALPS_UTILITY_CAST_HPP
8 #define ALPS_UTILITY_CAST_HPP
9 
10 #include <alps/config.hpp>
12 
13 #include <boost/bind.hpp>
14 
15 #include <string>
16 #include <complex>
17 #include <typeinfo>
18 #include <type_traits>
19 #include <algorithm>
20 #include <stdexcept>
21 #include <cstdio>
22 
23 namespace alps {
24 
25  struct bad_cast : public std::runtime_error {
26  bad_cast(std::string const & arg) : std::runtime_error(arg) {}
27  };
28 
29  template<typename U, typename T> inline U cast(T const &);
30 
31  namespace detail {
32 
33  template<typename U, typename T> struct is_cast {
34  static T t;
35  static char check(U);
36  static double check(...);
37  enum { value = sizeof(check(t)) / sizeof(char) };
38  };
39 
40  template<
41  typename U, typename T, typename X
42  > inline U cast_generic(T /*arg*/, X) {
43  throw bad_cast(
44  std::string("cannot cast from ")
45  + typeid(T).name()
46  + " to "
47  + typeid(U).name() + ALPS_STACKTRACE
48  );
49  return U();
50  }
51 
52  template<typename U, typename T> inline U cast_generic(
53  T arg, std::integral_constant<int, 1> const&
54  ) {
55  return arg;
56  }
57 
58  }
59 
60  template<typename U, typename T> struct cast_hook {
61  static inline U apply(T arg) {
62  return detail::cast_generic<U, T>(
63  arg, std::integral_constant<int, detail::is_cast<U, T>::value>()
64  );
65  }
66  };
67 
68  #define ALPS_CAST_STRING(T, p, c) \
69  template<> struct cast_hook<std::string, T > { \
70  static inline std::string apply( T arg) { \
71  char buffer[255]; \
72  if (sprintf(buffer, "%" p "" c, arg) < 0) \
73  throw std::runtime_error( \
74  "error casting from " #T " to string" + ALPS_STACKTRACE \
75  ); \
76  return buffer; \
77  } \
78  }; \
79  template<> struct cast_hook< T, std::string> { \
80  static inline T apply(std::string arg) { \
81  T value = 0; \
82  if (arg.size() && sscanf(arg.c_str(), "%" c, &value) < 0) \
83  throw std::runtime_error( \
84  "error casting from string to " #T ": " \
85  + arg + ALPS_STACKTRACE \
86  ); \
87  return value; \
88  } \
89  };
90  ALPS_CAST_STRING(short, "", "hd")
91  ALPS_CAST_STRING(int, "", "d")
92  ALPS_CAST_STRING(long, "", "ld")
93  ALPS_CAST_STRING(unsigned short, "", "hu")
94  ALPS_CAST_STRING(unsigned int, "", "u")
95  ALPS_CAST_STRING(unsigned long, "", "lu")
96  ALPS_CAST_STRING(float, ".8", "e")
97  ALPS_CAST_STRING(double, ".16", "le")
98  ALPS_CAST_STRING(long double, ".32", "Le")
99  ALPS_CAST_STRING(long long, "", "lld")
100  ALPS_CAST_STRING(unsigned long long, "", "llu")
101  #undef ALPS_CAST_STRING
102 
103  #define ALPS_CAST_STRING_CHAR(T, U) \
104  template<> struct cast_hook<std::string, T > { \
105  static inline std::string apply( T arg) { \
106  return cast_hook<std::string, U>::apply(arg); \
107  } \
108  }; \
109  template<> struct cast_hook<T, std::string> { \
110  static inline T apply(std::string arg) { \
111  return cast_hook< U , std::string>::apply(arg); \
112  } \
113  };
116  ALPS_CAST_STRING_CHAR(signed char, short)
117  ALPS_CAST_STRING_CHAR(unsigned char, unsigned short)
118  #undef ALPS_CAST_STRING_CHAR
119 
120  template<typename U, typename T> struct cast_hook<U, std::complex<T> > {
121  static inline U apply(std::complex<T> const & arg) {
122  return static_cast<U>(arg.real());
123  }
124  };
125 
126  template<typename U, typename T> struct cast_hook<std::complex<U>, T> {
127  static inline std::complex<U> apply(T const & arg) {
128  return cast<U>(arg);
129  }
130  };
131 
132  template<typename U, typename T> struct cast_hook<std::complex<U>, std::complex<T> > {
133  static inline std::complex<U> apply(std::complex<T> const & arg) {
134  return std::complex<U>(arg.real(), arg.imag());
135  }
136  };
137 
138  template<typename T> struct cast_hook<std::string, std::complex<T> > {
139  static inline std::string apply(std::complex<T> const & arg) {
140  return cast<std::string>(arg.real()) + "+" + cast<std::string>(arg.imag()) + "i";
141  }
142  };
143 
144  // TODO: also parse a+bi
145  template<typename T> struct cast_hook<std::complex<T>, std::string> {
146  static inline std::complex<T> apply(std::string const & arg) {
147  return cast<T>(arg);
148  }
149  };
150 
151  template<typename U, typename T> inline U cast(T const & arg) {
152  return cast_hook<U, T>::apply(arg);
153  }
154 
155  template<typename U, typename T> inline void cast(
156  U const * src, U const * end, T * dest
157  ) {
158  for (U const * it = src; it != end; ++it)
159  dest[it - src] = cast<T>(*it);
160  }
161 }
162 
163 #endif
static std::string apply(std::complex< T > const &arg)
Definition: cast.hpp:139
STL namespace.
#define ALPS_CAST_STRING_CHAR(T, U)
Definition: cast.hpp:103
static std::complex< U > apply(std::complex< T > const &arg)
Definition: cast.hpp:133
static std::complex< U > apply(T const &arg)
Definition: cast.hpp:127
bad_cast(std::string const &arg)
Definition: cast.hpp:26
static U apply(std::complex< T > const &arg)
Definition: cast.hpp:121
static std::complex< T > apply(std::string const &arg)
Definition: cast.hpp:146
U cast(T const &)
Definition: cast.hpp:151
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
static U apply(T arg)
Definition: cast.hpp:61
#define ALPS_CAST_STRING(T, p, c)
Definition: cast.hpp:68