473,545 Members | 2,599 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Problem with one-liner string conversion

Hi,

A few months back I remember reading through C++ newsgroups trying
to find a way to quickly convert a number to a C++ std::string. I
often see code like:

// Create a string that holds a number:
int num = 7; // for example
char tmp[24];
sprintf(tmp, "%d", num);
const std::string str = tmp;

but I wanted to see if there was a better way. I generally would use
this:

// Create a string that holds a number:
int num = 7;
std::ostringstr eam outStream; // #include <sstream>
outStream << num;
const std::string str = outStream.str() ;

and this works great, but just like the first example, it declares and
uses a temporary variable/object. What I'd have liked to see was some
sort of method in std::string that handled the conversion in one line,
like this:

// NOTE: not real code!
int num = 7;
const std::string str = std::string::nu mber(num);

While I didn't find what I was looking for, I did find an
interesting post, where someone posted this nice, simple function:

// Converts many things to a std::string:
#include <sstream>

template <typename T>
std::string toStdString(con st T &thing)
{
std::ostringstr eam os;
os << thing;
return os.str();
}

Using this function, I can now write code like this:

int num = 7;
const std::string str = toStdString(num );

This code is very clear, but it also has another benefit: Not only
can I easily convert integers and floats to a std::string, but I can
convert pretty much anything that I can send to std::cout.

But then I thought of something: Why even define a templated
function? I could write code like this:

int num = 7;
std::string str = (std::ostringst ream() << num).str();

It may not be as elegant as the toStdString() solution, but at least
it won't require me to define (or include a header file of) the
toStdString() function in every program I write. In addition, there's
no need to introduce a temporary variable to the current scope.

However, when I tried to compile this code, I got the following
error message:

testfile.cpp: In function `int main(int, char**)':
testfile.cpp:23 : error: 'struct std::basic_ostr eam<char,
std::char_trait s<char' has no member named 'str'

I can't figure out why I'm getting this error message. I mean, I'm
declaring a std::ostringstr eam object, using the "<<" operator on it
(which, I believe, returns the very same std::ostringstr eam object),
and then I call the ::str() method on it. std::ostringstr eam HAS to
have ::str() defined, otherwise the toStdString() function above
wouldn't compile.

What puzzles me is that I've successfully compiled similar things
with std::strings, like this:

// Prints "Hello, world!":
const char* word1 = "Hello";
const char* word2 = "world";
printf("%s", (word1 + std::string(", ") + word2 + "!\n").c_str()) ;

and have had no problems with it. (Basically, word1+std::stri ng(", ")
+word2+"!\n" returns a std::string, and the ::c_str() method is called
on it, passing its internal data to printf() to use before the
std::string goes out of scope.)

I would think that what I'm trying to do with std::ostringstr eam is
really no different, so it puzzles me why (std::ostringst ream() <<
num).str() generates a compiler error. Does anybody know why this
generates a compiler error?

Thanks in advance for any help.

-- Jean-Luc
Jun 27 '08 #1
9 3717
jl*****@hotmail .com wrote:
Hi,

A few months back I remember reading through C++ newsgroups trying
to find a way to quickly convert a number to a C++ std::string. I
often see code like:

// Create a string that holds a number:
int num = 7; // for example
char tmp[24];
sprintf(tmp, "%d", num);
const std::string str = tmp;

but I wanted to see if there was a better way. I generally would use
this:

// Create a string that holds a number:
int num = 7;
std::ostringstr eam outStream; // #include <sstream>
outStream << num;
const std::string str = outStream.str() ;

and this works great, but just like the first example, it declares and
uses a temporary variable/object. What I'd have liked to see was some
sort of method in std::string that handled the conversion in one line,
like this:

// NOTE: not real code!
int num = 7;
const std::string str = std::string::nu mber(num);

While I didn't find what I was looking for, I did find an
interesting post, where someone posted this nice, simple function:

// Converts many things to a std::string:
#include <sstream>

template <typename T>
std::string toStdString(con st T &thing)
{
std::ostringstr eam os;
os << thing;
return os.str();
}

Using this function, I can now write code like this:

int num = 7;
const std::string str = toStdString(num );

This code is very clear, but it also has another benefit: Not only
can I easily convert integers and floats to a std::string, but I can
convert pretty much anything that I can send to std::cout.

But then I thought of something: Why even define a templated
function? I could write code like this:

int num = 7;
std::string str = (std::ostringst ream() << num).str();

It may not be as elegant as the toStdString() solution, but at least
it won't require me to define (or include a header file of) the
toStdString() function in every program I write. In addition, there's
no need to introduce a temporary variable to the current scope.

However, when I tried to compile this code, I got the following
error message:

testfile.cpp: In function `int main(int, char**)':
testfile.cpp:23 : error: 'struct std::basic_ostr eam<char,
std::char_trait s<char' has no member named 'str'
Note that the operator<< you are invoking is inherited from the
std::basic_ostr eam<char>. Its return type is std::basic_ostr eam&. At that
point, all information about the underlying object being a string stream is
lost. An std::basic_ostr eam<charobject does not have a str() member
function. You need to cast back:

std::string str =
static_cast< std::ostringstr eam& >( std::ostringstr eam() << num ).str();
[snip]
BTW: you should just put toStdString into your library and use it. It is
much better than writing a cryptic line every time you want to convert
something. Also, you are creating a stringstream object in either case.
Whether it is a named local variable of a temporary doesn't really matter
all that much.
Best

Kai-Uwe Bux
Jun 27 '08 #2
jl*****@hotmail .com kirjutas:
>
int num = 7;
std::string str = (std::ostringst ream() << num).str();
ostringstream is derived from basic_ostream. The operator << you are
calling is the one from the basic_ostream class. It returns a reference to
itself as a reference to the basic_ostream class object. This class does
not have a str() member function.

As the object itself is actually ostringstream, you should be able to cast
it back to the correct type:

int num = 7;
std::string str = static_cast<std ::ostringstream &>(std::ostring stream() <<
num).str();

Of course, this makes the one-liner even uglier. What's wrong with the
helper function approach?

hth
Paavo
Jun 27 '08 #3
Kai-Uwe Bux wrote:
jl*****@hotmail .com wrote:
>Hi,
[snip]
> int num = 7;
std::string str = (std::ostringst ream() << num).str();

It may not be as elegant as the toStdString() solution, but at least
it won't require me to define (or include a header file of) the
toStdString( ) function in every program I write. In addition, there's
no need to introduce a temporary variable to the current scope.

However, when I tried to compile this code, I got the following
error message:

testfile.cpp : In function `int main(int, char**)':
testfile.cpp:2 3: error: 'struct std::basic_ostr eam<char,
std::char_trai ts<char' has no member named 'str'

Note that the operator<< you are invoking is inherited from the
std::basic_ostr eam<char>. Its return type is std::basic_ostr eam&. At that
point, all information about the underlying object being a string stream
is lost. An std::basic_ostr eam<charobject does not have a str() member
function. You need to cast back:

std::string str =
static_cast< std::ostringstr eam& >( std::ostringstr eam() << num ).str();
[snip]

Ah, and just for kicks, now try:

#include <sstream>
#include <iostream>

int main ( void ) {
char const * message = "Hello world.\n";
std::cout <<
static_cast< std::ostringstr eam& >
( std::ostringstr eam() << message ).str();
}

and interpret the output.
I re-iterate: go with the toStdString() solution.
Best

Kai-Uwe Bux
Jun 27 '08 #4
On Jun 17, 3:28*pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
Kai-Uwe Bux wrote:
jl_p...@hotmail .com wrote:
Hi,

[snip]
* *int num = 7;
* *std::string str = (std::ostringst ream() << num).str();
It may not be as elegant as the toStdString() solution, but at least
it won't require me to define (or include a header file of) the
toStdString() function in every program I write. *In addition, there's
no need to introduce a temporary variable to the current scope.
* *However, when I tried to compile this code, I got the following
error message:
testfile.cpp: In function `int main(int, char**)':
testfile.cpp:23 : error: 'struct std::basic_ostr eam<char,
std::char_trait s<char' has no member named 'str'
Note that the operator<< you are invoking is inherited from the
std::basic_ostr eam<char>. Its return type is std::basic_ostr eam&. At that
point, all information about the underlying object being a string stream
is lost. An std::basic_ostr eam<charobject does not have a str() member
function. You need to cast back:
* std::string str =
* static_cast< std::ostringstr eam& >( std::ostringstr eam() << num ).str();

[snip]

Ah, and just for kicks, now try:

#include <sstream>
#include <iostream>

int main ( void ) {
* char const * message = "Hello world.\n";
* std::cout <<
* * static_cast< std::ostringstr eam& >
* * ( std::ostringstr eam() << message ).str();

}

and interpret the output.

I re-iterate: go with the toStdString() solution.

Best

Kai-Uwe Bux

Or get a hold of the boost libraries (boost.org) and use its
lexical_cast<>( ). It not only converts from string to number and
number to string. But from anything to anything. As long as you can
use a stream to convert them. Even better boost is the semi-offical
testing ground for stuff that will be considered for the next
standard. So it is highly tested and widely addopted.

#include <boost/lexical_cast.hp p>

int main()
{
std::string val("567");
int num = boost::lexical_ cast<int>(val);
}
Jun 27 '08 #5
On Jun 18, 1:03 am, Martin York <Martin.YorkAma ...@gmail.comwr ote:
On Jun 17, 3:28 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
Kai-Uwe Bux wrote:
jl_p...@hotmail .com wrote:
[snip]
Or get a hold of the boost libraries (boost.org) and use its
lexical_cast<>( ). It not only converts from string to number
and number to string. But from anything to anything.
I'm not sure that I'd consider that an advantage. It doesn't
make sense to convert anything to anything (and going through
the textual representation, which boost::lexical_ cast does, is
not necessarily the correct way to convert x to y).

Even in the case of conversion to string, I'm not sure just how
often a generic solution is appropriate; you probably don't want
to format a value representing an interest rate (percent) in the
same way you'd format a value representing a monetary value.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #6
On Jun 18, 1:34*am, James Kanze <james.ka...@gm ail.comwrote:
On Jun 18, 1:03 am, Martin York <Martin.YorkAma ...@gmail.comwr ote:
Or get a hold of the boost libraries (boost.org) and use its
lexical_cast<>( ). It not only converts from string to number
and number to string. But from anything to anything.

I'm not sure that I'd consider that an advantage. *It doesn't
make sense to convert anything to anything (and going through
the textual representation, which boost::lexical_ cast does, is
not necessarily the correct way to convert x to y).
Context is everything.
I hope (and imagine) other readers did not read into my last reply
that I was suggesting that lexical_cast<>( ) should be used to convert
from a type to any other arbitory type. Where appropriate stream can
be used (via lexical_cast<>( )) in a type safe way to convert types
appropriately (Its usage will ALWAYS depend on the context of the
problem). 'Normally' this will be <Type=String or String =>
<Type>. But as with all rules and complex systems it usage is not
limited to just that.

Martin
Jun 27 '08 #7

Thank you all for all your help. I really appreciate it.

But before I end this post, let me answer a question some have been
asking:

On Jun 17, 3:21 pm, Paavo Helde <nob...@ebi.eew rote:
>
What's wrong with the helper function approach?
Nothing, really. I just wanted to know why the line:

std::string str = (std::ostringst ream() << num).str();

wouldn't compile. That line to me is fairly simple (even thought some
might call it "ugly"), that if I were to find a just-as-simple
approach, I'd use that.

However, I agree that the fix that uses the static_cast:

std::string str =
static_cast<std ::ostringstream &>
(std::ostringst ream() << num).str();

is not that "pretty" and that there are more readable ways to do the
same thing.

(Basically, I wanted to know why the code wouldn't compile. I
didn't mean to imply that I rejected the helper-function approach.
Sorry for the confusion.)

Again, thanks for all your help.

-- Jean-Luc
Jun 27 '08 #8
On Jun 18, 8:22 pm, Martin York <Martin.YorkAma ...@gmail.comwr ote:
On Jun 18, 1:34 am, James Kanze <james.ka...@gm ail.comwrote:
On Jun 18, 1:03 am, Martin York <Martin.YorkAma ...@gmail.comwr ote:
Or get a hold of the boost libraries (boost.org) and use
its lexical_cast<>( ). It not only converts from string to
number and number to string. But from anything to
anything.
I'm not sure that I'd consider that an advantage. It
doesn't make sense to convert anything to anything (and
going through the textual representation, which
boost::lexical_ cast does, is not necessarily the correct way
to convert x to y).
Context is everything.
I hope (and imagine) other readers did not read into my last
reply that I was suggesting that lexical_cast<>( ) should be
used to convert from a type to any other arbitory type. Where
appropriate stream can be used (via lexical_cast<>( )) in a
type safe way to convert types appropriately (Its usage will
ALWAYS depend on the context of the problem). 'Normally' this
will be <Type=String or String =<Type>. But as with all
rules and complex systems it usage is not limited to just
that.
Yes. The problem with lexical_cast is that it is too
convenient; it sort of works in a large number of cases where it
probably shouldn't (and then fails for some particular values
which you forgot to test).

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #9
On Jun 18, 9:50*pm, jl_p...@hotmail .com wrote:
* *std::string str = (std::ostringst ream() << num).str();

wouldn't compile. *That line to me is fairly simple (even thought some
might call it "ugly"), that if I were to find a just-as-simple
approach, I'd use that.
Using a utility class, a string builder, you can achieve this terse
solution:

string s = SB << num;

See here for discussion, description and limitations:

http://groups.google.com/group/comp....00421feca71ea1

Regards,
Vidar Hasfjord
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
3736
by: Kostatus | last post by:
I have a virtual function in a base class, which is then overwritten by a function of the same name in a publically derived class. When I call the function using a pointer to the derived class (ClassB* b; b->func(); ) the base-class function is called instead of the new function in the derived class. All other similar functions (virtual in...
4
2389
by: Leslaw Bieniasz | last post by:
Cracow, 20.09.2004 Hello, I need to implement a library containing a hierarchy of classes together with some binary operations on objects. To fix attention, let me assume that it is a hierarchy of algebraic matrices with the addition operation. Thus, I want to have a virtual base class class Matr;
15
2308
by: Tamblyne | last post by:
This problem has got to have a simple solution and I can't be the first person who has ever handled it. Perhaps Google is no help because I'm not using the right terms? (I did find one post on-point, but no one responded to it.) I have a two column layout with a header and a footer. If the "content" is longer than the "navigation", there...
15
2409
by: Ken Allen | last post by:
I have been developing a suite of assemblies over the past couple of weeks, and this afternoon somethign started misbehaving. If I do not run the IDE and compiler the code from the command line, the compilation seems to work properly almost all of the time. More on this later. If I launch one copy of the IDE, then I can usually compile...
4
2337
by: Sa¹o Zagoranski | last post by:
Hi! I'm writing a simple 3D First person shooter game. It is a multiplayer game, where all the players connect to one server.
8
3370
by: nick | last post by:
I have a problem and I've been using a cheezy work around and was wondering if anyone else out there has a better solution. The problem: Let's say I have a web application appA. Locally, I set it up as C:\domains\appA. Locally, my IIS root points to C:\domains. I don't point it to C:\domains\appA since if I have an appB under C:\domains I...
9
9672
by: Ecohouse | last post by:
I have a main form with two subforms. The first subform has the child link to the main form identity key. subform1 - Master Field: SK Child Field: TrainingMasterSK The second subform has a master-child link to the first subform. subform2 - Master Field: subTrainingModule.Form!TrainingModuleTopicSK Child Field: TrainingModuleTopicSK
9
5744
by: HC | last post by:
Hello, all, I started out thinking my problems were elsewhere but as I have worked through this I have isolated my problem, currently, as a difference between MSDE and SQL Express 2005 (I'll just call it Express for simplicity). I have, to try to simplify things, put the exact same DB on two systems, one running MSDE and one running...
1
2642
by: Kijoki | last post by:
Hi, I am having this big headache causing problem for over seven months now! I run an internetcafe and for over the past seven months I have been getting this really weird problem in which my internet connection drops (router has this security built-in in which it restarts) and then comes back on in about 30 seconds time! The LAN setup is...
9
3627
by: AceKnocks | last post by:
I am working on a framework design problem in which I have to design a C++ based framework capable of solving three puzzles for now but actually it should work with a general puzzle of any kind and I need your able help in this activity. Objective - In this activity you will design a framework capable of solving any puzzle of a specific type...
0
7490
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7682
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7935
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7449
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6009
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
3479
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3465
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1911
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
734
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.