From: Mikko Rasa Date: Sat, 1 Dec 2012 20:50:39 +0000 (+0200) Subject: Filter the types that get fallback lexical conversion operators X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=ff0d3252cad08280b9c320b3fea5a11c80406c23;p=libs%2Fcore.git Filter the types that get fallback lexical conversion operators Only enable the operators for types that already have iostream formatting operators defined. Having them exist for everything would interfere with some other stuff I'm going to commit in a moment. --- diff --git a/source/core/meta.h b/source/core/meta.h index 0034512..9230965 100644 --- a/source/core/meta.h +++ b/source/core/meta.h @@ -11,6 +11,7 @@ template struct RemoveConst { typedef T Type; }; + template struct RemoveReference { typedef T Type; }; @@ -19,6 +20,34 @@ template struct RemoveReference { typedef T Type; }; + +template +struct EnableIf; + +template +struct EnableIf +{ typedef R Yes; }; + +template +struct EnableIf +{ typedef R No; }; + + +/** +Common fragments used in SFINAE-based decider constructs. +*/ +struct Sfinae +{ + struct Yes { char c[2]; }; + struct No { char c; }; + + template + struct Evaluate + { + enum { value = (s==sizeof(Yes)) }; + }; +}; + } // namespace Msp #endif diff --git a/source/strings/lexicalcast.h b/source/strings/lexicalcast.h index c6a17da..80963f4 100644 --- a/source/strings/lexicalcast.h +++ b/source/strings/lexicalcast.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "fmt.h" namespace Msp { @@ -89,7 +90,39 @@ void operator>>(const LexicalConverter &, std::string &); // Generic operators using stringstream template -void operator<<(LexicalConverter &c, const T &v) +struct HasFormattedOutput: Sfinae +{ + static std::ostream &s; + static T &v; + + /* The expression must depend on the template parameter, or the compiler + will give an error. */ + template + static Yes f(int (*)[sizeof(s<::v)]); + template + static No f(...); + + enum { value = Evaluate(0))>::value }; +}; + +template +struct HasFormattedInput: Sfinae +{ + static std::istream &s; + static T &v; + + template + static Yes f(int (*)[sizeof(s>>HasFormattedOutput::v)]); + template + static No f(...); + + enum { value = Evaluate(0))>::value }; +}; + + +template +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);