Discussion:
The std::to_string/to_wstring functions should allow the user to specify the base of the numeric conversion
(too old to reply)
Ricky65
2011-08-09 01:47:42 UTC
Permalink
C++0x provides the useful std::to_string/to_wstring functions for
converting numeric values to strings. However, I was disappointed to
learn that users can't specify the base of the conversion; at the
moment the std::to_string/to_wstring functions only convert a numeric
to a base ten string. I think this is an oversight and find this very
limiting.

In contrast , the similar non-standard but widespread C function itoa
allows the user to specify the base of the conversion. e.g.
hexadecimal, octal and binary. For example:

int x = 23;
char buffer [32];
itoa(x, buffer, 2) //represent the value as a string in base 2
(binary)

I find it rather embarrassing that a C function, albeit non-standard,
has more functionality than these C++ functions.

I understand that the overloaded std::to_string/to_wstring functions
call sprintf and wsprintf. The problem with this approach is that
sprintf can only convert to decimal, hexadecimal and octal bases. Why
do these functions have to use sprintf? I don't know why it couldn't
have been left to implementers to write their own versions of these
functions without these limitations.

It would be preferable if the user could select the base of the
numeric conversion.

The solution is simple, provide an extra argument for the base with a
default argument of 10. For example:

std::string to_string(int val, int base = 10);

This would be backward compatible with the current functions as it
would default to base ten (decimal) conversion as the functions
currently do whilst at the same time allowing the user to specify the
base of the numeric conversion.

If something like this doesn't get implemented, I suspect people will
use itoa or its variants, or roll their own similar function, reducing
the utility of the std::to_string/to_wstring functions.

Kind regards
Riccardo Marcangelo
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Ulrich Eckhardt
2011-08-10 20:13:11 UTC
Permalink
Post by Ricky65
C++0x provides the useful std::to_string/to_wstring functions for
converting numeric values to strings. However, I was disappointed to
learn that users can't specify the base of the conversion; at the
moment the std::to_string/to_wstring functions only convert a numeric
to a base ten string. I think this is an oversight and find this very
limiting.
I've been using similar functions for quite some time. In no case did I ever
find the need to specify the formatting. OTOH, I rarely use these to
stringize builtin types either, because these can already be written to a
stream as they are. That said, I do sometimes provide overloads of
to_string() for my own custom data types. These then sometimes use a
different base for numbers.
Post by Ricky65
In contrast , the similar non-standard but widespread C function itoa
allows the user to specify the base of the conversion. e.g.
int x = 23;
char buffer [32];
itoa(x, buffer, 2) //represent the value as a string in base 2
(binary)
I find it rather embarrassing that a C function, albeit non-standard,
has more functionality than these C++ functions.
I tend to let personal feeling out of such discussions. I'd rather be
embarrassed writing code like the above, which overflows the buffer as soon
x becomes large. ;)
Post by Ricky65
I understand that the overloaded std::to_string/to_wstring functions
call sprintf and wsprintf. The problem with this approach is that
sprintf can only convert to decimal, hexadecimal and octal bases. Why
do these functions have to use sprintf? I don't know why it couldn't
have been left to implementers to write their own versions of these
functions without these limitations.
I don't know the exact specification and I'm not sure I understand what you
are saying here. Is your only complaint that sprintf doesn't allow
formatting as binary?
Post by Ricky65
It would be preferable if the user could select the base of the
numeric conversion.
The solution is simple, provide an extra argument for the base with a
std::string to_string(int val, int base = 10);
There are two reasons against this:
1. creeping featuritis
The next one will want a flag to specify whether hex numbers have a 0x
prefix or not. Then someone will want to specify that the hex digits use
uppercase A-F. Then, flexible zero-padding will be requested. Don't even get
me started on other data types, those offer another set of possible flags
and options.
Post by Ricky65
This would be backward compatible with the current functions as it
would default to base ten (decimal) conversion as the functions
currently do whilst at the same time allowing the user to specify the
base of the numeric conversion.
2. incompatibility
This is at the moment not that important, since the API is new, but
generally changing an API is difficult. Still, even today, a function taking
two argument is simply not one taking one argument, even if one of the two
arguments has a default. You can't use the same type of function pointer for
these.
Post by Ricky65
If something like this doesn't get implemented, I suspect people will
use itoa or its variants, or roll their own similar function, reducing
the utility of the std::to_string/to_wstring functions.
Assume a function like this:

template<typename P1, typename P2>
void print(char const* fmt, P1 const& p1, P2 const& p2);

This function would simply call to_string() on the given objects in order to
format them, and then replace some placeholders in 'fmt' before printing the
result. First thing to note is that there is no place here to pass
parameters, there simply is no place to put them. Still, you can use this in
order to format a number using hexadecimal:

struct hex
{
hex(unsigned v): value(v) {}
unsigned value;
};

std::string to_string(hex_value const& v)
{
std::stringstream s;
s << "0x" << std::setfill('0') << std::setwidth(8) << v.value;
return s.str();
}

Note: This should determine the width from the size, make sure the value is
unsigned and be a template. Also it could avoid the overhead of a
stringstream, the size of the result is known after all.


Anyway, you can now then call:

print("answer = %1", hex(66));

As you see, if you need you can extend this to special needs without
breaking the generality of the approach. Similarly, you can overload
to_string() for your own types.


Summary: I don't think that it's as bad as you make it sound. I do believe
that provisions like above that format numbers using different bases would
be a useful addition.

Uli
--
Domino Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Andrew
2011-08-12 22:44:03 UTC
Permalink
Post by Ulrich Eckhardt
Post by Ricky65
C++0x provides the useful std::to_string/to_wstring functions for
converting numeric values to strings.
Not that useful IMO.
Post by Ulrich Eckhardt
Post by Ricky65
I think this is an oversight and find this very limiting.
So do I.
Post by Ulrich Eckhardt
Post by Ricky65
In contrast , the similar non-standard but widespread C function itoa
allows the user to specify the base of the conversion. e.g.
hexadecimal, octal and binary.
Unfortunately it is very non-std. I haven't seen it used very much
because of portability issues.
Post by Ulrich Eckhardt
Post by Ricky65
The solution is simple, provide an extra argument for the base with a
std::string to_string(int val, int base = 10);
This problem has already been solved in the java world:

String s = Integer.toString(ivalue, radix);

IMO C++ should offer a similar interface.
Post by Ulrich Eckhardt
1. creeping featuritis
I disagree. This has not happened in java. Besides, it is already
possible to do more fancy formatting with sprintf. This too has been
adopted in other languages, e.g python.
Post by Ulrich Eckhardt
2. incompatibility
This is at the moment not that important, since the API is new, but
generally changing an API is difficult.
That's why it is useful to see what java did and that the interface
remained stable without being superceeded.
Post by Ulrich Eckhardt
Still, even today, a function taking
two argument is simply not one taking one argument, even if one of the two
arguments has a default.
I agree with this one. See the java interface where there is not an
overloading of toString where a radix of ten will be used. You have to
give the radix. I think you should in C++ as well. Also, look at
strtol. I know its C so default arguments are not available but it
shows that C++ has conversion functions available (via C) where the
radix has to be specified.
Post by Ulrich Eckhardt
Uli
--
Domino Laser GmbH
Regards,

Andrew Marlow
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Daniel Krügler
2011-08-24 23:44:20 UTC
Permalink
Post by Ricky65
C++0x provides the useful std::to_string/to_wstring functions for
converting numeric values to strings. However, I was disappointed to
learn that users can't specify the base of the conversion; at the
moment the std::to_string/to_wstring functions only convert a numeric
to a base ten string. I think this is an oversight and find this very
limiting.
I don't think, this is an oversight, it was the result of providing a
consistent specification of tiny little helper functions based on C API.
Post by Ricky65
In contrast , the similar non-standard but widespread C function itoa
allows the user to specify the base of the conversion. e.g.
int x = 23;
char buffer [32];
itoa(x, buffer, 2) //represent the value as a string in base 2
(binary)
I find it rather embarrassing that a C function, albeit non-standard,
has more functionality than these C++ functions.
Sorry, but this is like comparing apples with oranges to me: *Of-course*
some extension will provide more functionality, otherwise it would not
be an extension. I wonder why no-one asks for extending the printf API
to allow formatting of integral types to arbitrary bases between 2 and
36 - this seems to me like the actual defect here.
Post by Ricky65
I understand that the overloaded std::to_string/to_wstring functions
call sprintf and wsprintf. The problem with this approach is that
sprintf can only convert to decimal, hexadecimal and octal bases. Why
do these functions have to use sprintf? I don't know why it couldn't
have been left to implementers to write their own versions of these
functions without these limitations.
It would be preferable if the user could select the base of the
numeric conversion.
I agree.
Post by Ricky65
The solution is simple, provide an extra argument for the base with a
std::string to_string(int val, int base = 10);
This would be backward compatible with the current functions as it
would default to base ten (decimal) conversion as the functions
currently do whilst at the same time allowing the user to specify the
base of the numeric conversion.
This is not an interface question. Of-course it could be declared this
way. But there is currently no way to specify the semantics of such a
function similarly to the other ones. My suggestion would be to ask the
C committee to extend (s)printf for extended formatting capabilities for
integral types to fix this problem.

And if this would be fixed, one could also consider to generalize the
basefield manipulators ([basefield.manip]) for arbitrary base values.
Post by Ricky65
If something like this doesn't get implemented, I suspect people will
use itoa or its variants, or roll their own similar function, reducing
the utility of the std::to_string/to_wstring functions.
Unless C does not provide extended formatting choices, they will use
itoa, no matter what. I strongly suggest to ask C for extending the
formatting choices in regard to fix this.

HTH & Greetings from Bremen,

- Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Loading...