From ff0d3252cad08280b9c320b3fea5a11c80406c23 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 1 Dec 2012 22:50:39 +0200 Subject: [PATCH] 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. --- source/core/meta.h | 29 +++++++++++++++++++++++++++ source/strings/lexicalcast.h | 38 ++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 2 deletions(-) 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); -- 2.43.0