1 #ifndef MSP_STRINGS_LEXICALCAST_H_
2 #define MSP_STRINGS_LEXICALCAST_H_
7 #include <msp/core/meta.h>
13 Thrown for errors in lexical conversions.
15 class lexical_error: public std::runtime_error
18 lexical_error(const std::string &w): runtime_error(w) { }
19 virtual ~lexical_error() throw() { }
24 Thrown when the format is unsuitable for the type being converted.
26 class format_mismatch: public lexical_error
29 format_mismatch(const std::string &w): lexical_error(w) { }
30 virtual ~format_mismatch() throw() { }
35 Helper class for lexical_cast to facilitate operator overloading.
37 class LexicalConverter
45 LexicalConverter(const Fmt &f): fmt(f), filled(false) { }
46 LexicalConverter(const std::string &s, const Fmt &f): fmt(f), filled(true), buf(s) { }
48 const Fmt &get_fmt() const { return fmt; }
49 const std::string &get() const;
50 void result(const std::string &);
54 void operator<<(LexicalConverter &, char);
55 void operator<<(LexicalConverter &, signed char);
56 void operator<<(LexicalConverter &, short);
57 void operator<<(LexicalConverter &, int);
58 void operator<<(LexicalConverter &, long);
59 void operator<<(LexicalConverter &, unsigned char);
60 void operator<<(LexicalConverter &, unsigned short);
61 void operator<<(LexicalConverter &, unsigned);
62 void operator<<(LexicalConverter &, unsigned long);
64 void operator<<(LexicalConverter &, long long);
65 void operator<<(LexicalConverter &, unsigned long long);
67 void operator<<(LexicalConverter &, bool);
68 void operator<<(LexicalConverter &, float);
69 void operator<<(LexicalConverter &, double);
70 void operator<<(LexicalConverter &, long double);
71 void operator<<(LexicalConverter &, const std::string &);
72 void operator<<(LexicalConverter &, const char *);
73 void operator<<(LexicalConverter &, const void *);
75 void operator>>(const LexicalConverter &, char &);
76 void operator>>(const LexicalConverter &, signed char &);
77 void operator>>(const LexicalConverter &, short &);
78 void operator>>(const LexicalConverter &, int &);
79 void operator>>(const LexicalConverter &, long &);
80 void operator>>(const LexicalConverter &, unsigned char &);
81 void operator>>(const LexicalConverter &, unsigned short &);
82 void operator>>(const LexicalConverter &, unsigned int &);
83 void operator>>(const LexicalConverter &, unsigned long &);
85 void operator>>(const LexicalConverter &, long long &);
86 void operator>>(const LexicalConverter &, unsigned long long &);
88 void operator>>(const LexicalConverter &, bool &);
89 void operator>>(const LexicalConverter &, float &);
90 void operator>>(const LexicalConverter &, double &);
91 void operator>>(const LexicalConverter &, long double &);
92 void operator>>(const LexicalConverter &, std::string &);
94 // Generic operators using stringstream
96 struct CheckFormattedOutput: Sfinae
98 static std::ostream &s;
100 static Yes f(int (*)[sizeof(s<<T())]);
104 struct CheckFormattedInput: Sfinae
106 static std::istream &s;
108 static Yes f(int (*)[sizeof(s>>reinterpret_cast<T &>(s))]);
112 template<typename T> struct HasFormattedOutput: Sfinae::Evaluate<CheckFormattedOutput, T> { };
113 template<typename T> struct HasFormattedInput: Sfinae::Evaluate<CheckFormattedInput, T> { };
117 typename EnableIf<HasFormattedOutput<T>::value, void>::Yes
118 operator<<(LexicalConverter &c, const T &v)
120 std::ostringstream ss;
121 ss << c.get_fmt() << v;
126 typename EnableIf<HasFormattedInput<T>::value, void>::Yes
127 operator>>(const LexicalConverter &c, T &v)
129 std::istringstream ss(c.get());
130 ss.setf(std::ios_base::fmtflags(0), std::ios_base::skipws);
132 if(ss.fail() || !ss.eof())
133 throw lexical_error("conversion failure");
137 Helper struct to provide partial template specialization.
139 template<typename T, typename F>
143 struct LexicalCast<T, std::string>
145 static T cast(const std::string &s, const Fmt &f = Fmt())
147 LexicalConverter conv(s, f);
155 struct LexicalCast<std::string, F>
157 static std::string cast(const F &v, const Fmt &f = Fmt())
159 LexicalConverter conv(f);
166 struct LexicalCast<std::string, std::string>
168 static std::string cast(const std::string &v, const Fmt &f = Fmt())
170 LexicalConverter conv(f);
176 /** Perform a lexical conversion between a string and another type. The source
177 type can normally be deduced by the compiler, so this can be used just like the
178 standard C++ casts. A format may additionally be specified to force a specific
180 template<typename T, typename F>
181 inline T lexical_cast(const F &v, const Fmt &f = Fmt())
183 return LexicalCast<T, F>::cast(v, f);