Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Why extracting string from stringstream(a) fails?

Reply
Thread Tools

Why extracting string from stringstream(a) fails?

 
 
Mc Lauren Series
Guest
Posts: n/a
 
      10-24-2009
#include <iostream>
#include <sstream>

using namespace std;

int main()
{
string a("test");
string b;
stringstream(a) >> b;
}

When I try to execute this code, I get errors:

foo.c: In function 'int main()':
foo.c:10: error: no match for 'operator>>' in
'std::basic_stringstream<char, std::char_traits<char>,
std::allocator<char> >(((const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&)((const
std::basic_string<char, std::char_traits<char>, std::allocator<char>
>*)(& a))), std:perator|(_S_out, _S_in)) >> b'


Why does this error occur? Isn't stringstream(a) supposed to behave
just like a stream? With cout I can extract string into a string
variable. Then why not here?
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      10-24-2009
Mc Lauren Series wrote:
> #include <iostream>
> #include <sstream>
>
> using namespace std;
>
> int main()
> {
> string a("test");
> string b;
> stringstream(a) >> b;
> }
>
> When I try to execute this code, I get errors:
>
> foo.c: In function 'int main()':
> foo.c:10: error: no match for 'operator>>' in
> 'std::basic_stringstream<char, std::char_traits<char>,
> std::allocator<char> >(((const std::basic_string<char,
> std::char_traits<char>, std::allocator<char> >&)((const
> std::basic_string<char, std::char_traits<char>, std::allocator<char>
>> *)(& a))), std:perator|(_S_out, _S_in)) >> b'

>
> Why does this error occur? Isn't stringstream(a) supposed to behave
> just like a stream? With cout I can extract string into a string
> variable. Then why not here?


The operator >> is a non-member. It takes the first argument by a
non-const reference, which cannot be initialized with a temporary.
Define a named variable and you will be able to do what you want:

stringstream sa(a);
sa >> b;

There is a trick to overcome this particular limitation, but it's not
the best approach. You can do something like that

stringstream(a) >> boolalpha >> b;

which invokes a non-const member function (which is OK for temporaries)
and the function (that "outputs" a manipulator) returns a non-const
reference, which then can be passed to the non-member operator<<.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
 
 
 
Mc Lauren Series
Guest
Posts: n/a
 
      10-25-2009
On Oct 25, 3:28*am, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> Mc Lauren Series wrote:
> > #include <iostream>
> > #include <sstream>

>
> > using namespace std;

>
> > int main()
> > {
> > * * string a("test");
> > * * string b;
> > * * stringstream(a) >> b;
> > }

>
> > When I try to execute this code, I get errors:

>
> > foo.c: In function 'int main()':
> > foo.c:10: error: no match for 'operator>>' in
> > 'std::basic_stringstream<char, std::char_traits<char>,
> > std::allocator<char> >(((const std::basic_string<char,
> > std::char_traits<char>, std::allocator<char> >&)((const
> > std::basic_string<char, std::char_traits<char>, std::allocator<char>
> >> *)(& a))), std:perator|(_S_out, _S_in)) >> b'

>
> > Why does this error occur? Isn't stringstream(a) supposed to behave
> > just like a stream? With cout I can extract string into a string
> > variable. Then why not here?

>
> The operator >> is a non-member. *It takes the first argument by a
> non-const reference, which cannot be initialized with a temporary.
> Define a named variable and you will be able to do what you want:
>
> * * *stringstream sa(a);
> * * *sa >> b;
>
> There is a trick to overcome this particular limitation, but it's not
> the best approach. *You can do something like that
>
> * * *stringstream(a) >> boolalpha >> b;
>
> which invokes a non-const member function (which is OK for temporaries)
> and the function (that "outputs" a manipulator) returns a non-const
> reference, which then can be passed to the non-member operator<<.
>
> V
> --
> Please remove capital 'A's when replying by e-mail
> I do not respond to top-posted replies, please don't ask


If >> is a non-member, why does this work?

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
string a("1234");
// string b;
int b;
stringstream(a) >> b;
cout << b << endl;
}


If we change the data type of b to int, the code works fine but not
with b as string. Why?
 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      10-25-2009
On 25/10/09 06:17, Mc Lauren Series wrote:
> On Oct 25, 3:28 am, Victor Bazarov<v.Abaza...@comAcast.net> wrote:
>> Mc Lauren Series wrote:
>>> #include<iostream>
>>> #include<sstream>

>>
>>> using namespace std;

>>
>>> int main()
>>> {
>>> string a("test");
>>> string b;
>>> stringstream(a)>> b;
>>> }

>>
>>> When I try to execute this code, I get errors:

>>
>>> foo.c: In function 'int main()':
>>> foo.c:10: error: no match for 'operator>>' in
>>> 'std::basic_stringstream<char, std::char_traits<char>,
>>> std::allocator<char> >(((const std::basic_string<char,
>>> std::char_traits<char>, std::allocator<char> >&)((const
>>> std::basic_string<char, std::char_traits<char>, std::allocator<char>
>>>> *)(& a))), std:perator|(_S_out, _S_in))>> b'

>>
>>> Why does this error occur? Isn't stringstream(a) supposed to behave
>>> just like a stream? With cout I can extract string into a string
>>> variable. Then why not here?

>>
>> The operator>> is a non-member. It takes the first argument by a
>> non-const reference, which cannot be initialized with a temporary.
>> Define a named variable and you will be able to do what you want:
>>
>> stringstream sa(a);
>> sa>> b;
>>
>> There is a trick to overcome this particular limitation, but it's not
>> the best approach. You can do something like that
>>
>> stringstream(a)>> boolalpha>> b;
>>
>> which invokes a non-const member function (which is OK for temporaries)
>> and the function (that "outputs" a manipulator) returns a non-const
>> reference, which then can be passed to the non-member operator<<.


>
> If>> is a non-member, why does this work?
>


Some stream operators are member functions, others are not. Member
functions can be called on temporary objects. boolalpha is handled by a
member function which returns std::istream&. That std::istream& can than
be accepted by both member and non-member operator>> functions.

> #include<iostream>
> #include<sstream>
> #include<string>
>
> using namespace std;
>
> int main()
> {
> string a("1234");
> // string b;
> int b;
> stringstream(a)>> b;
> cout<< b<< endl;
> }
>
>
> If we change the data type of b to int, the code works fine but not
> with b as string. Why?


Because extracting into an integer is handled by a member function of
std::istream base class of std::stringstream.

Here is another trick to turn a temporary into an l-value, so that any
operator>> can work on a temporary stream object:

template<class T>
inline T& lvalue(T const& t) {
return const_cast<T&>(t);
}

This function template is supposed to be used like this:

lvalue(stringstream(a)) >> ...;

Alternatively, boost::lexical_cast<> converts between types using
streams and its usage is simpler:

int b = boost::lexical_cast<int>("1234");

Using streams directly as you do allows to extract more than one value
at once though.

--
Max
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-25-2009
Maxim Yegorushkin wrote:

> On 25/10/09 06:17, Mc Lauren Series wrote:
>> On Oct 25, 3:28 am, Victor Bazarov<v.Abaza...@comAcast.net> wrote:
>>> Mc Lauren Series wrote:
>>>> #include<iostream>
>>>> #include<sstream>
>>>
>>>> using namespace std;
>>>
>>>> int main()
>>>> {
>>>> string a("test");
>>>> string b;
>>>> stringstream(a)>> b;
>>>> }
>>>
>>>> When I try to execute this code, I get errors:
>>>
>>>> foo.c: In function 'int main()':
>>>> foo.c:10: error: no match for 'operator>>' in
>>>> 'std::basic_stringstream<char, std::char_traits<char>,
>>>> std::allocator<char> >(((const std::basic_string<char,
>>>> std::char_traits<char>, std::allocator<char> >&)((const
>>>> std::basic_string<char, std::char_traits<char>, std::allocator<char>
>>>>> *)(& a))), std:perator|(_S_out, _S_in))>> b'
>>>
>>>> Why does this error occur? Isn't stringstream(a) supposed to behave
>>>> just like a stream? With cout I can extract string into a string
>>>> variable. Then why not here?
>>>
>>> The operator>> is a non-member. It takes the first argument by a
>>> non-const reference, which cannot be initialized with a temporary.
>>> Define a named variable and you will be able to do what you want:
>>>
>>> stringstream sa(a);
>>> sa>> b;
>>>
>>> There is a trick to overcome this particular limitation, but it's not
>>> the best approach. You can do something like that
>>>
>>> stringstream(a)>> boolalpha>> b;
>>>
>>> which invokes a non-const member function (which is OK for temporaries)
>>> and the function (that "outputs" a manipulator) returns a non-const
>>> reference, which then can be passed to the non-member operator<<.

>
>>
>> If>> is a non-member, why does this work?
>>

>
> Some stream operators are member functions, others are not. Member
> functions can be called on temporary objects. boolalpha is handled by a
> member function which returns std::istream&. That std::istream& can than
> be accepted by both member and non-member operator>> functions.
>
>> #include<iostream>
>> #include<sstream>
>> #include<string>
>>
>> using namespace std;
>>
>> int main()
>> {
>> string a("1234");
>> // string b;
>> int b;
>> stringstream(a)>> b;
>> cout<< b<< endl;
>> }
>>
>>
>> If we change the data type of b to int, the code works fine but not
>> with b as string. Why?

>
> Because extracting into an integer is handled by a member function of
> std::istream base class of std::stringstream.
>
> Here is another trick to turn a temporary into an l-value, so that any
> operator>> can work on a temporary stream object:
>
> template<class T>
> inline T& lvalue(T const& t) {
> return const_cast<T&>(t);
> }
>

Although this will be ill-formed because it requires the stream to have a
copy constructor. You could also use this trickery which i believe is safe:

template<typename T>
struct Lv {
T t, &tr;
Lv():t(), tr(t) {}
};

template<typename T>
T &lvalue(T &t = Lv<T>().tr) { return t; }

"lvalue<stringstream>()" now gives an lvalue of type stringstream, but this
doesn't allow passing arguments to its constructor

 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-25-2009
Johannes Schaub (litb) wrote:

> Maxim Yegorushkin wrote:
>
>> On 25/10/09 06:17, Mc Lauren Series wrote:
>>> On Oct 25, 3:28 am, Victor Bazarov<v.Abaza...@comAcast.net> wrote:
>>>> Mc Lauren Series wrote:
>>>>> #include<iostream>
>>>>> #include<sstream>
>>>>
>>>>> using namespace std;
>>>>
>>>>> int main()
>>>>> {
>>>>> string a("test");
>>>>> string b;
>>>>> stringstream(a)>> b;
>>>>> }
>>>>
>>>>> When I try to execute this code, I get errors:
>>>>
>>>>> foo.c: In function 'int main()':
>>>>> foo.c:10: error: no match for 'operator>>' in
>>>>> 'std::basic_stringstream<char, std::char_traits<char>,
>>>>> std::allocator<char> >(((const std::basic_string<char,
>>>>> std::char_traits<char>, std::allocator<char> >&)((const
>>>>> std::basic_string<char, std::char_traits<char>, std::allocator<char>
>>>>>> *)(& a))), std:perator|(_S_out, _S_in))>> b'
>>>>
>>>>> Why does this error occur? Isn't stringstream(a) supposed to behave
>>>>> just like a stream? With cout I can extract string into a string
>>>>> variable. Then why not here?
>>>>
>>>> The operator>> is a non-member. It takes the first argument by a
>>>> non-const reference, which cannot be initialized with a temporary.
>>>> Define a named variable and you will be able to do what you want:
>>>>
>>>> stringstream sa(a);
>>>> sa>> b;
>>>>
>>>> There is a trick to overcome this particular limitation, but it's not
>>>> the best approach. You can do something like that
>>>>
>>>> stringstream(a)>> boolalpha>> b;
>>>>
>>>> which invokes a non-const member function (which is OK for temporaries)
>>>> and the function (that "outputs" a manipulator) returns a non-const
>>>> reference, which then can be passed to the non-member operator<<.

>>
>>>
>>> If>> is a non-member, why does this work?
>>>

>>
>> Some stream operators are member functions, others are not. Member
>> functions can be called on temporary objects. boolalpha is handled by a
>> member function which returns std::istream&. That std::istream& can than
>> be accepted by both member and non-member operator>> functions.
>>
>>> #include<iostream>
>>> #include<sstream>
>>> #include<string>
>>>
>>> using namespace std;
>>>
>>> int main()
>>> {
>>> string a("1234");
>>> // string b;
>>> int b;
>>> stringstream(a)>> b;
>>> cout<< b<< endl;
>>> }
>>>
>>>
>>> If we change the data type of b to int, the code works fine but not
>>> with b as string. Why?

>>
>> Because extracting into an integer is handled by a member function of
>> std::istream base class of std::stringstream.
>>
>> Here is another trick to turn a temporary into an l-value, so that any
>> operator>> can work on a temporary stream object:
>>
>> template<class T>
>> inline T& lvalue(T const& t) {
>> return const_cast<T&>(t);
>> }
>>

> Although this will be ill-formed because it requires the stream to have a
> copy constructor. You could also use this trickery which i believe is
> safe:
>
> template<typename T>
> struct Lv {
> T t, &tr;
> Lv():t(), tr(t) {}
> };
>
> template<typename T>
> T &lvalue(T &t = Lv<T>().tr) { return t; }
>
> "lvalue<stringstream>()" now gives an lvalue of type stringstream, but
> this doesn't allow passing arguments to its constructor
>

If you want, though, you can change it to

template<typename T>
struct Lv {
T t, &tr;
Lv():t(), tr(t) {}
template<typename U1>
Lv(U1 const& u1):t(u1), tr(t) { }
};

And you can do Lv<stringstream>("hello").tr to get the lvalue, which isn't
too bad i think, it just doesn't look nice. Packaged into a macro

#define LVALUE(TY, EX) Lv<Ty> EX . tr

It can look much better like LVALUE(stringstream,("hello"))


 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      10-25-2009
On 25/10/09 18:13, Johannes Schaub (litb) wrote:
> Maxim Yegorushkin wrote:
>
>> On 25/10/09 06:17, Mc Lauren Series wrote:
>>> On Oct 25, 3:28 am, Victor Bazarov<v.Abaza...@comAcast.net> wrote:
>>>> Mc Lauren Series wrote:
>>>>> #include<iostream>
>>>>> #include<sstream>
>>>>
>>>>> using namespace std;
>>>>
>>>>> int main()
>>>>> {
>>>>> string a("test");
>>>>> string b;
>>>>> stringstream(a)>> b;
>>>>> }
>>>>
>>>>> When I try to execute this code, I get errors:
>>>>
>>>>> foo.c: In function 'int main()':
>>>>> foo.c:10: error: no match for 'operator>>' in
>>>>> 'std::basic_stringstream<char, std::char_traits<char>,
>>>>> std::allocator<char> >(((const std::basic_string<char,
>>>>> std::char_traits<char>, std::allocator<char> >&)((const
>>>>> std::basic_string<char, std::char_traits<char>, std::allocator<char>
>>>>>> *)(& a))), std:perator|(_S_out, _S_in))>> b'
>>>>
>>>>> Why does this error occur? Isn't stringstream(a) supposed to behave
>>>>> just like a stream? With cout I can extract string into a string
>>>>> variable. Then why not here?
>>>>
>>>> The operator>> is a non-member. It takes the first argument by a
>>>> non-const reference, which cannot be initialized with a temporary.
>>>> Define a named variable and you will be able to do what you want:
>>>>
>>>> stringstream sa(a);
>>>> sa>> b;
>>>>
>>>> There is a trick to overcome this particular limitation, but it's not
>>>> the best approach. You can do something like that
>>>>
>>>> stringstream(a)>> boolalpha>> b;
>>>>
>>>> which invokes a non-const member function (which is OK for temporaries)
>>>> and the function (that "outputs" a manipulator) returns a non-const
>>>> reference, which then can be passed to the non-member operator<<.

>>
>>>
>>> If>> is a non-member, why does this work?
>>>

>>
>> Some stream operators are member functions, others are not. Member
>> functions can be called on temporary objects. boolalpha is handled by a
>> member function which returns std::istream&. That std::istream& can than
>> be accepted by both member and non-member operator>> functions.
>>
>>> #include<iostream>
>>> #include<sstream>
>>> #include<string>
>>>
>>> using namespace std;
>>>
>>> int main()
>>> {
>>> string a("1234");
>>> // string b;
>>> int b;
>>> stringstream(a)>> b;
>>> cout<< b<< endl;
>>> }
>>>
>>>
>>> If we change the data type of b to int, the code works fine but not
>>> with b as string. Why?

>>
>> Because extracting into an integer is handled by a member function of
>> std::istream base class of std::stringstream.
>>
>> Here is another trick to turn a temporary into an l-value, so that any
>> operator>> can work on a temporary stream object:
>>
>> template<class T>
>> inline T& lvalue(T const& t) {
>> return const_cast<T&>(t);
>> }
>>

> Although this will be ill-formed because it requires the stream to have a
> copy constructor.


Interesting.

My understanding is that a copy constructor is only required when copy
initialization is involved or when a conversion is made to initialize a
function argument. In this case there is no copy initialization or
conversion happening. Therefore, the code must be well formed.

Could you elaborate you point please?

--
Max
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      10-25-2009
* Maxim Yegorushkin:
> On 25/10/09 18:13, Johannes Schaub (litb) wrote:
>> Maxim Yegorushkin wrote:
>>
>>>
>>> Here is another trick to turn a temporary into an l-value, so that any
>>> operator>> can work on a temporary stream object:
>>>
>>> template<class T>
>>> inline T& lvalue(T const& t) {
>>> return const_cast<T&>(t);
>>> }
>>>

>> Although this will be ill-formed because it requires the stream to have a
>> copy constructor.

>
> Interesting.
>
> My understanding is that a copy constructor is only required when copy
> initialization is involved or when a conversion is made to initialize a
> function argument. In this case there is no copy initialization or
> conversion happening. Therefore, the code must be well formed.
>
> Could you elaborate you point please?


It's different in C++98 and C++0x (C++03 is just C++98 with corrections).

The argument passing is defined as copy initialization. And in C++98 the
implementation is allowed to make any number of copies of an rvalue actual
argument passed to 'T const&' formal argument, or for any copy initialization.
Which means that the type must provide a suitable copy constructor. For example,
that means that you can't do this thing with a std::auto_ptr. Or a stream.

In C++0x the implementation can't make such copies when it has an rvalue of
correct type, it must just pass (initialize the reference with) a direct
reference to the rvalue object. So this impacts on std::auto_ptr semantics,
which are different in C++0x. But with C++0x you don't have to and really
shouldn't use std::auto_ptr anyway, and even in C++98 passing std::auto_ptr by
reference to const is bad, and the "direct" passing provides a measure of
sanity.


Cheers & hth.,

- Alf
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      10-25-2009
* Alf P. Steinbach:
> * Maxim Yegorushkin:
>> On 25/10/09 18:13, Johannes Schaub (litb) wrote:
>>> Maxim Yegorushkin wrote:
>>>
>>>>
>>>> Here is another trick to turn a temporary into an l-value, so that any
>>>> operator>> can work on a temporary stream object:
>>>>
>>>> template<class T>
>>>> inline T& lvalue(T const& t) {
>>>> return const_cast<T&>(t);
>>>> }
>>>>
>>> Although this will be ill-formed because it requires the stream to
>>> have a
>>> copy constructor.

>>
>> Interesting.
>>
>> My understanding is that a copy constructor is only required when copy
>> initialization is involved or when a conversion is made to initialize
>> a function argument. In this case there is no copy initialization or
>> conversion happening. Therefore, the code must be well formed.
>>
>> Could you elaborate you point please?

>
> It's different in C++98 and C++0x (C++03 is just C++98 with corrections).
>
> The argument passing is defined as copy initialization. And in C++98 the
> implementation is allowed to make any number of copies of an rvalue
> actual argument passed to 'T const&' formal argument, or for any copy
> initialization. Which means that the type must provide a suitable copy
> constructor. For example, that means that you can't do this thing with a
> std::auto_ptr. Or a stream.
>
> In C++0x the implementation can't make such copies when it has an rvalue
> of correct type, it must just pass (initialize the reference with) a
> direct reference to the rvalue object. So this impacts on std::auto_ptr
> semantics, which are different in C++0x. But with C++0x you don't have
> to and really shouldn't use std::auto_ptr anyway, and even in C++98
> passing std::auto_ptr by reference to const is bad, and the "direct"
> passing provides a measure of sanity.


Uhm, remove one "even", sorry.

Cheers,

- Alf
 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      10-26-2009
Alf P. Steinbach wrote:
> * Maxim Yegorushkin:
>> On 25/10/09 18:13, Johannes Schaub (litb) wrote:
>>> Maxim Yegorushkin wrote:
>>>
>>>>
>>>> Here is another trick to turn a temporary into an l-value, so that any
>>>> operator>> can work on a temporary stream object:
>>>>
>>>> template<class T>
>>>> inline T& lvalue(T const& t) {
>>>> return const_cast<T&>(t);
>>>> }
>>>>
>>> Although this will be ill-formed because it requires the stream to
>>> have a
>>> copy constructor.

>>
>> Interesting.
>>
>> My understanding is that a copy constructor is only required when copy
>> initialization is involved or when a conversion is made to initialize
>> a function argument. In this case there is no copy initialization or
>> conversion happening. Therefore, the code must be well formed.
>>
>> Could you elaborate you point please?

>
> It's different in C++98 and C++0x (C++03 is just C++98 with corrections).
>
> The argument passing is defined as copy initialization. And in C++98 the
> implementation is allowed to make any number of copies of an rvalue
> actual argument passed to 'T const&' formal argument, or for any copy
> initialization. Which means that the type must provide a suitable copy
> constructor. For example, that means that you can't do this thing with a
> std::auto_ptr. Or a stream.


Even more interesting.

Given the following declaration:

void foo(int& ref);

Could you explain how ref argument can possibly be copy-initialized please?

--
Max
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
why why why why why Mr. SweatyFinger ASP .Net 4 12-21-2006 01:15 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
why adodb.strem downloding works for everything but self extracting files? Avi ASP General 2 05-06-2004 05:27 AM
Extracting a string Mar Thomas Java 9 01-15-2004 04:54 AM
extracting integers from string R Java 2 07-25-2003 03:47 AM



Advertisments