
Vladimir.Batov@wrsa.com.au wrote:
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
I would initially like to see if we can agree on
1) creating boost::string (or some other as descriptive name) namespace;
Could we come up with another name for the namespace? The string namespace looks too general to me and may potentially clash with std::string if "using namespace boost; using namespace std;" is written in the users' code. I suggest using boost::strings namespace (note the trailing 's'). In order to have the clear naming of the res of the interface, my further suggestions are bellow.
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:
namespace bs = boost::strings;
int i; std::string s;
1) int i_from_s = boost::string::to<int>(s); // throws
bs::to_string?
2) std::string s_from_i = boost::string::from<int>(i);
bs::from_string?
3) bool s_is_i = boost::string::is<int>(i);
I like the way it is.
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);
Everything looks fine with me, except that I would suggest using a more explicit syntax for the default value specification. Like this: boost::string::to<int>(s).with_default(-1);