Make lexical_cast symmetric
authorMikko Rasa <tdb@tdb.fi>
Sat, 1 Dec 2012 09:27:45 +0000 (11:27 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 1 Dec 2012 09:27:45 +0000 (11:27 +0200)
It has bugged me for a long time that lexical_cast took only the type of
the non-string side as a template argument.  Fix it so that it always
takes both target and source types.  The source type can be deduced, so
this only requires changes to invocations that cast things to strings.

source/io/seekable.cpp
source/stringcodec/except.cpp
source/strings/format.h
source/strings/lexicalcast.h
tests/lexicalcast.cpp

index a75cf33e67725fe6e978f98d927681cce59e16d5..35ab5a05104fef55fbe625a3e55cdff2d1b18590 100644 (file)
@@ -45,7 +45,7 @@ namespace Msp {
 namespace IO {
 
 bad_seek::bad_seek(SeekOffset offset, SeekType type):
-       runtime_error(type==S_BEG ? lexical_cast(offset) :
+       runtime_error(type==S_BEG ? lexical_cast<string>(offset) :
                type==S_CUR ? format("CUR%+d", offset) :
                type==S_END ? format("END%+d", offset) :
                format("SeekType(%d)", type))
index 1e1393cf00e99486b46526c94257d9b6c72bcdc3..b4d07ece559706025677393ea019a9cce39799c0 100644 (file)
@@ -22,7 +22,7 @@ string invalid_sequence::format_sequence(const string::const_iterator &begin, co
        {
                if(!result.empty())
                        result += ' ';
-               result += lexical_cast(static_cast<unsigned char>(*i), Fmt().fill('0').width(2).hex().uppercase());
+               result += lexical_cast<string>(static_cast<unsigned char>(*i), Fmt().fill('0').width(2).hex().uppercase());
        }
        return result;
 }
index 6d8f739a436c3abaa8fdbbbdc7292e5dfb803d1d..65d10dffa585bb6e272db7d1d20a71a07b6a0a42 100644 (file)
@@ -24,7 +24,7 @@ public:
        template<typename T>
        Formatter &operator()(const T &a)
        {
-               result += lexical_cast(a, get_conversion());
+               result += lexical_cast<std::string>(a, get_conversion());
                advance();
                return *this;
        }
index b6cba3b89498c32b86576c66087d9472a0a4c680..c6a17da3491d053b6460399fddea6473ea1ca839 100644 (file)
@@ -106,23 +106,51 @@ void operator>>(const LexicalConverter &c, T &v)
                throw lexical_error("conversion failure");
 }
 
-// The main interface to the lexical conversion machinery
+// Helper struct to provide partial template specialization
+
+template<typename T, typename F>
+struct LexicalCast;
 
 template<typename T>
-inline T lexical_cast(const std::string &s, const Fmt &f = Fmt())
+struct LexicalCast<T, std::string>
 {
-       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<typename T>
-inline std::string lexical_cast(const T &v, const Fmt &f = Fmt())
+template<typename F>
+struct LexicalCast<std::string, F>
+{
+       static std::string cast(const F &v, const Fmt &f = Fmt())
+       {
+               LexicalConverter conv(f);
+               conv<<v;
+               return conv.get();
+       }
+};
+
+template<>
+struct LexicalCast<std::string, std::string>
+{
+       static std::string cast(const std::string &v, const Fmt &f = Fmt())
+       {
+               LexicalConverter conv(f);
+               conv<<v;
+               return conv.get();
+       }
+};
+
+// The main interface to the lexical conversion machinery
+
+template<typename T, typename F>
+inline T lexical_cast(const F &v, const Fmt &f = Fmt())
 {
-       LexicalConverter conv(f);
-       conv<<v;
-       return conv.get();
+       return LexicalCast<T, F>::cast(v, f);
 }
 
 } // namespace Msp
index a983f1b146675aa7d5dd4883f7ef6a3d99a5ddc4..2a4a7877aa87fc53b5a718c429c47a09b8e4205c 100644 (file)
@@ -207,7 +207,7 @@ void LexicalCastTests::test_values(const Value<T> *values)
 {
        for(const Value<T> *i=values; i->format; ++i)
        {
-               string result = lexical_cast(i->value, i->format);
+               string result = lexical_cast<string>(i->value, i->format);
                expect_equal(result, result==i->result, format("result == \"%s\"", c_escape(i->result)));
        }
 }