There are various flavors of converting a string to a number (e.g. _ttol, _ttof), but not all conversions are readily available and require different functions. I propose a single from_tstring function added in "defs.h" such as the following:
template <class T> T from_tstring (const tstring& s) { T n; tistringstream ts; ts.str(s); ts >> n; return n; }
This would allow any type of conversion from a tstring to a type that supports streaming (e.g. char, int, long, long long, unsigned versions of those). Example use:
tstring s = _T("+123456890123456"); auto n = from_tstring<unsigned long long>(s); auto c = from_tstring<tchar>(s);
After the above executes, n = 123456890123456 and c = _T('+').
Anonymous
I think
from_tstring
is a very good idea. It is symmetric withto_tstring
and, like you point out, replaces the myriad of alternatives by a simple go-to solution fortstring
, making it less likely that the user will write old-style code that is non-compliant with Unicode build mode.A few comments:
from_tstring
needs error handling.tistringstream
's constructor takingtstring
can be used.Suggested improvement:
PS. I think
to_tstring
andfrom_tstring
need a better home than "defs.h". I think we really should have "tstring.h", which in turn could include "private/strmdefs.h", wheretistringstream
etc. is defined. Or, we could simply remove the latter and include it literally in "tstring.h".Last edit: Vidar Hasfjord 2021-02-19
I have now implemented
to_tstring
andfrom_tstring
in the new header "include/owl/tstring.h" on the Owlet branch [r2942].Related
Commit: [r2942]
Hi Vidar,
Actually I think it and to_string is a not-so-good idea.
As do I. But I think it further illustrates the need to extend tstring, which can't be done. I believe it in essence belongs in TStringC, with implicit conversions (constructors) and overload operators, simply allowing the following:
However, since you already added a to_tstring and TStringC has not been approved, I suggested the from_tstring.
Hi Vidar,
In my usage of these new definitions, I have found them to be lacking for my purpose. Here are some definitions I use (in brevity, without error checking):
The most commonly used for me is to_tstring_locale, which for example when called with:
gives me "-1,234,567,890" in the US locale. Other locales might give such results as "1.234.567.890-" or "(1 234 567 890)" as grouping and signed quantities yield different results. The inverse from_tstring_locale would also interpret such strings and return the proper result.
However, there are other cases where even this is insufficient, such as using floating point numbers and wanting to specify control over the number of decimal places, or fill and width values, or monetary values. So I also have to_tstring/from_tstring with a stream argument so that the user can set these appropriately before calling them.
Hi Joe, sorry for the late reply. I am travelling (work/vacation) so I do not have much time for OWLNext at the moment. But I will return with more feedback as time allows.
Looks useful! And I cannot immediately see any ill-effects. Could we use simple overloading of "to_tstring" rather than add "to_tstring_locale"? Or are there overloading issues?
Hi Vidar,
No need to apologize for being on vacation! Hope you are having a wonderful time.
My reason for adding "to_tstring_locale" was to be able to use the default environment locale (i.e., locale("")) — which for me uses the US locale — without having to specify it while not breaking the existing behaviour of "to_tstring" (which in essence has a default locale("C")). I find both versions useful. The new addition is more user-friendly for displaying numeric values, but the existing one is needed for example, generating HTML entities for values greater than 999 (e.g., ‥) in which such group separators are undesired.
Makes sense.
I have made some corrections and improvements to from_tstring in Owlet [r5382].
The new specialisations make from_tstring the proper converse to to_string for std::string and std::wstring. For example:
Previously, using from_string with std::string and std::wstring as the template argument T caused compilation error, unless T matched owl::tstring. And if T matched owl::tstring, then only the first word of the string would be returned, not the whole string, i.e. causing our test above to fail.
Note that these specialisations are implemented in terms of the new functions ConvertToNarrow and ConvertToWide [feature-requests:#174]. So an alternative to from_tstring is to use ConvertToNarrow and ConvertToWide instead, for perhaps clearer code. Though, in generic code, the from_tstring specialisations may still be useful, since the selection of the conversion operation depends on the template argument passed. However, the specialisations are mainly added for completeness and symmetry.
Related
Commit: [r5382]
Feature Requests: #174
Last edit: Vidar Hasfjord 2021-02-20