
Based on the previous string-conversion-related discussion that revolved around lexical_cast (started with http://lists.boost.org/Archives/boost/2009/01/147013.php) and Dave's suggestion (http://lists.boost.org/Archives/boost/2009/02/147995.php) I would like to propose to create a new boost::string namespace where I'd expect all string-related functionality might be logically housed. Dave already mentioned that "Jeff Garland had a really nice set of proposed extensions to std::string that could live in the same space". My immediate interest/proposal in that namespace would be the string-conversion functionality. The basics of that functionality are currently handled by lexical_cast but need extended and unambiguously tagged as *string*-related conversions. During discussion I've got a strong impression that the majority of people, the lexical_cast author (Kevlin) and the maintainer (Alex) strongly favor leaving lexical_cast as-is and having a fresh start capitalizing on the past experiences. Therefore I'd like to propose the string-conversion functionality that'd be housed inside that mentioned boost::string namespace. This proposal of mine probably is not as conventional as I have no implementation code to show. That is because before committing to it any further (or dragging someone else into it) I would initially like to see if we can agree on 1) creating boost::string (or some other as descriptive name) namespace; 2) the interface for that proposed string-conversion functionality. After that I expect the implementation to be largely a technical issue.
From the user point the interface I'd like to propose might look like the following:
int i; std::string s; 1) int i_from_s = boost::string::to<int>(s); // throws 2) std::string s_from_i = boost::string::from<int>(i); 3) bool s_is_i = boost::string::is<int>(i); The above convert a string to an integer (#1), an integer to a string (#2) and check if conversion is possible (#3). #1 and #2 behave like lexical_cast currently does (throw on failure). #3 is a non-throwing check if #1 will succeed (to avoid handling an exception thrown by #1). For example, int i_from_s = boost::string::is<int>(s) ? boost::string::to<int>(s) // safe to request conversion : some-failure-value; I like to/from names as they allow me to read the code as it was merely English -- "string to int", "string from int". I expect string::to() and string:;from() to return a helper object as Dave suggested namespace string { template <class T> struct value { operator T() const; // throws iff parse unsuccessful bool good() const; // true iff parse will succeed ... }; } That'll allow as to make the interface consistent and extendable/chainable: 4) int i_from_s = boost::string::to<int>(s)(-1); The above is a non-throwing variation of #1 with the default value provided for failed conversion. 5) int i_from_s = boost::string::to<int>(s)(std::hex); 6) std::string s_from_i = boost::string::from<int>(i)(std::hex); The above is variations of #1 and #2 with the std::hex manipulator/formatter applied. That "chained" approach would allow to keep the interface consistency without sacrificing the flexibility. For example, 7) int i_from_s = boost::string::to<int>(s)(-1)(std::hex)(yet-another-manipulator); or add some other features when the need arises. Off the cuff the actual conversion might look something along the following lines: template<class T, class Char> boost::string::value::operator T() { std::basic_istringstream<Char> stream(string_); if (manipulators) stream >> manipulator_ >> ... >> value_; else stream >> value_; if (stream.fail()) if (no_default) throw something; else return default_value_; return value_; } Thanks, Vladimir.