X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fstrings%2Flexicalcast.h;h=22b45e88c55eef60e433b6253d0070b77c9242a5;hp=b6cba3b89498c32b86576c66087d9472a0a4c680;hb=4f04dc8e2dcb48d524c141cb14ce05b655608454;hpb=c7afef88380ebebc8c2b04e48664d73281ec8848 diff --git a/source/strings/lexicalcast.h b/source/strings/lexicalcast.h index b6cba3b..22b45e8 100644 --- a/source/strings/lexicalcast.h +++ b/source/strings/lexicalcast.h @@ -4,12 +4,13 @@ #include #include #include +#include #include "fmt.h" namespace Msp { /** -Thrown for errors in lexical conversions +Thrown for errors in lexical conversions. */ class lexical_error: public std::runtime_error { @@ -19,6 +20,9 @@ public: }; +/** +Thrown when the format is unsuitable for the type being converted. +*/ class format_mismatch: public lexical_error { public: @@ -34,14 +38,15 @@ class LexicalConverter { private: Fmt fmt; + bool filled; std::string buf; public: - LexicalConverter(const Fmt &f): fmt(f) { } - LexicalConverter(const std::string &s, const Fmt &f): fmt(f), buf(s) { } + LexicalConverter(const Fmt &f): fmt(f), filled(false) { } + LexicalConverter(const std::string &s, const Fmt &f): fmt(f), filled(true), buf(s) { } const Fmt &get_fmt() const { return fmt; } - const std::string &get() const { return buf; } + const std::string &get() const; void result(const std::string &); }; @@ -88,41 +93,94 @@ void operator>>(const LexicalConverter &, std::string &); // Generic operators using stringstream +struct CheckFormattedOutput: Sfinae +{ + static std::ostream &s; + template + static Yes f(int (*)[sizeof(s<(s))]); + using Sfinae::f; +}; + +struct CheckFormattedInput: Sfinae +{ + static std::istream &s; + template + static Yes f(int (*)[sizeof(s>>reinterpret_cast(s))]); + using Sfinae::f; +}; + +template struct HasFormattedOutput: Sfinae::Evaluate { }; +template struct HasFormattedInput: Sfinae::Evaluate { }; + + template -void operator<<(LexicalConverter &c, const T &v) +typename EnableIf::value, void>::Yes +operator<<(LexicalConverter &c, const T &v) { std::ostringstream ss; - ss< -void operator>>(const LexicalConverter &c, T &v) +typename EnableIf::value, void>::Yes +operator>>(const LexicalConverter &c, T &v) { std::istringstream ss(c.get()); ss.setf(std::ios_base::fmtflags(0), std::ios_base::skipws); - ss>>v; + ss >> v; if(ss.fail() || !ss.eof()) throw lexical_error("conversion failure"); } -// The main interface to the lexical conversion machinery +/** +Helper struct to provide partial template specialization. +*/ +template +struct LexicalCast; template -inline T lexical_cast(const std::string &s, const Fmt &f = Fmt()) +struct LexicalCast { - LexicalConverter conv(s, f); - T result; - conv>>result; - return result; -} + static T cast(const std::string &s, const Fmt &f = Fmt()) + { + LexicalConverter conv(s, f); + T result; + conv >> result; + return result; + } +}; -template -inline std::string lexical_cast(const T &v, const Fmt &f = Fmt()) +template +struct LexicalCast +{ + static std::string cast(const F &v, const Fmt &f = Fmt()) + { + LexicalConverter conv(f); + conv << v; + return conv.get(); + } +}; + +template<> +struct LexicalCast +{ + static std::string cast(const std::string &v, const Fmt &f = Fmt()) + { + LexicalConverter conv(f); + conv << v; + return conv.get(); + } +}; + +/** Perform a lexical conversion between a string and another type. The source +type can normally be deduced by the compiler, so this can be used just like the +standard C++ casts. A format may additionally be specified to force a specific +interpretation. */ +template +inline T lexical_cast(const F &v, const Fmt &f = Fmt()) { - LexicalConverter conv(f); - conv<::cast(v, f); } } // namespace Msp