Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > operator void* , stream extractor and built in types

Reply
Thread Tools

operator void* , stream extractor and built in types

 
 
ma740988
Guest
Posts: n/a
 
      08-25-2004
The conversion function ios_base:perator void* () calls good() on
its stream and returns the result.

I searched Dikumware but came up short, so I'm assuming operator void*
looks like

operator void*()
{
return (good() ? void*(this) : 0 );
}

Yes/No?

//// 2
Assume input_file has the contents
25 130 "Sarah"

class Test
{
public:
Test() { } ;
Test( int age_, int weight_, string name_)
: Age(age_)
, Weight(weight_)
, Name(name_)
{ } ;
~Test() { };

friend ostream& operator << ( ostream&, Test& );
friend istream& operator >> ( istream&, Test& );

void SaveAVec(Test &);
vector<Test> Employ1;

void WriteAllToScreen()
{
ifstream in("input_file.txt");
if (!in)
{
cerr << "error opening file... ";
exit(-1);
}
vector<Test>InVec;
Test Employ1;

while (in >> Employ1)
InVec.push_back(Employ1);

vector<Test>::iterator iter = InVec.begin(); // test
for ( ; iter != InVec.end(); ++iter )
cout << *iter << "\t";

in.close();
}

private:
int Age ;
int Weight;
string Name;
};

int main()
{
Test vec_test3;
//Test vec_test3(25, 124, "Sarah");
vec_test3.WriteAllToScreen();
//cout << vec_test3;
}

Extractors - as i understand it - parse information expected by the
destination object according to it's type. In this case the
information (25 130 "Sarah") and the type (Test) are two unrelated
entities, hence I'd expect the stream to fail. The fact that that
operator >> and subsequently the conversion operator got called for
Employ1 object - a UDT - is somewhat of a mystery to me. It further
leads me to believe that the Employ1 looks like Test Employ1(25, 130,
"Sarah"). Where have I gone wrong?

This makes sense to me
double f;
cin >> f;

assume f's input was 1.5. Now data and type match.


An aside: I realize the 'correct way' would be along the lines of ...

istream& operator >> ( istream& is, Test& rhs )
{
//cout << " istream& >>";
is >> rhs.Age;
is >> rhs.Weight;
is >> rhs.Name;

return is;
}
ostream& operator << ( ostream& os, Test& rhs )
{
//cout << "\t";
os << rhs.Age << '\n';
os << rhs.Weight << '\n';
os << rhs.Name << '\n';

return os;
}
 
Reply With Quote
 
 
 
 
David Hilsee
Guest
Posts: n/a
 
      08-25-2004
"ma740988" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) m...
> The conversion function ios_base:perator void* () calls good() on
> its stream and returns the result.
>
> I searched Dikumware but came up short, so I'm assuming operator void*
> looks like
>
> operator void*()
> {
> return (good() ? void*(this) : 0 );
> }
>
> Yes/No?


Did you look at Dinkumware's description the mmber functions of basic_ios?
They're pretty clear. In particular, operator void*'s description leaves
little to interpretation. It would look like this:

operator void*() const {
return fail() ? 0 : this /* or some other non-null value */;
}

It's not the same as what you wrote.

> //// 2
> Assume input_file has the contents
> 25 130 "Sarah"
>
> class Test
> {
> public:
> Test() { } ;
> Test( int age_, int weight_, string name_)
> : Age(age_)
> , Weight(weight_)
> , Name(name_)
> { } ;
> ~Test() { };
>
> friend ostream& operator << ( ostream&, Test& );
> friend istream& operator >> ( istream&, Test& );
>
> void SaveAVec(Test &);
> vector<Test> Employ1;
>
> void WriteAllToScreen()
> {
> ifstream in("input_file.txt");
> if (!in)
> {
> cerr << "error opening file... ";
> exit(-1);
> }
> vector<Test>InVec;
> Test Employ1;
>
> while (in >> Employ1)
> InVec.push_back(Employ1);
>
> vector<Test>::iterator iter = InVec.begin(); // test
> for ( ; iter != InVec.end(); ++iter )
> cout << *iter << "\t";
>
> in.close();
> }
>
> private:
> int Age ;
> int Weight;
> string Name;
> };
>
> int main()
> {
> Test vec_test3;
> //Test vec_test3(25, 124, "Sarah");
> vec_test3.WriteAllToScreen();
> //cout << vec_test3;
> }
>
> Extractors - as i understand it - parse information expected by the
> destination object according to it's type. In this case the
> information (25 130 "Sarah") and the type (Test) are two unrelated
> entities, hence I'd expect the stream to fail. The fact that that
> operator >> and subsequently the conversion operator got called for
> Employ1 object - a UDT - is somewhat of a mystery to me. It further
> leads me to believe that the Employ1 looks like Test Employ1(25, 130,
> "Sarah"). Where have I gone wrong?


Why do you consider the information unrelated? What conversion operator?
What's "wrong" with reading that data from the file? It sounds like
reasonable behavior to me.

> This makes sense to me
> double f;
> cin >> f;
>
> assume f's input was 1.5. Now data and type match.
>
>
> An aside: I realize the 'correct way' would be along the lines of ...
>
> istream& operator >> ( istream& is, Test& rhs )
> {
> //cout << " istream& >>";
> is >> rhs.Age;
> is >> rhs.Weight;
> is >> rhs.Name;
>
> return is;
> }
> ostream& operator << ( ostream& os, Test& rhs )
> {
> //cout << "\t";
> os << rhs.Age << '\n';
> os << rhs.Weight << '\n';
> os << rhs.Name << '\n';
>
> return os;
> }


I don't know if there is necessarily a single "correct" way. What you wrote
looks like a reasonable implementation.

--
David Hilsee


 
Reply With Quote
 
 
 
 
ma740988
Guest
Posts: n/a
 
      08-25-2004
"David Hilsee" <(E-Mail Removed)> wrote in message

>
> > //// 2
> > Assume input_file has the contents
> > 25 130 "Sarah"
> >
> > class Test
> > {
> > public:
> > Test() { } ;
> > Test( int age_, int weight_, string name_)
> > : Age(age_)
> > , Weight(weight_)
> > , Name(name_)
> > { } ;
> > ~Test() { };
> >
> > friend ostream& operator << ( ostream&, Test& );
> > friend istream& operator >> ( istream&, Test& );
> >
> > void SaveAVec(Test &);
> > vector<Test> Employ1;
> >
> > void WriteAllToScreen()
> > {
> > ifstream in("input_file.txt");
> > if (!in)
> > {
> > cerr << "error opening file... ";
> > exit(-1);
> > }
> > vector<Test>InVec;
> > Test Employ1;
> >
> > while (in >> Employ1)
> > InVec.push_back(Employ1);
> >
> > vector<Test>::iterator iter = InVec.begin(); // test
> > for ( ; iter != InVec.end(); ++iter )
> > cout << *iter << "\t";
> >
> > in.close();
> > }
> >
> > private:
> > int Age ;
> > int Weight;
> > string Name;
> > };
> >
> > int main()
> > {
> > Test vec_test3;
> > //Test vec_test3(25, 124, "Sarah");
> > vec_test3.WriteAllToScreen();
> > //cout << vec_test3;
> > }
> >
> > Extractors - as i understand it - parse information expected by the
> > destination object according to it's type. In this case the
> > information (25 130 "Sarah") and the type (Test) are two unrelated
> > entities, hence I'd expect the stream to fail. The fact that that
> > operator >> and subsequently the conversion operator got called for
> > Employ1 object - a UDT - is somewhat of a mystery to me. It further
> > leads me to believe that the Employ1 looks like Test Employ1(25, 130,
> > "Sarah"). Where have I gone wrong?

>
> Why do you consider the information unrelated? What conversion operator?
> What's "wrong" with reading that data from the file? It sounds like
> reasonable behavior to me.


I dont have a problem with reading the data from the file. My issue
where the data is being inserted/stored. ie. a UDT which for some
reason doesn't seem logical to me.

class X
{
public:
X() {}
~X() {}
};

void Store()
{
while ( cin >> X ) // implicit call to the conversion operator
void* operator()
//
}

Hence if the user entered 1.5 where in 'X' is the 1.5 being stored?

Here again this is logical
double f;
cin >> f;
 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      08-25-2004
"ma740988" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) m...
<snip>
> I dont have a problem with reading the data from the file. My issue
> where the data is being inserted/stored. ie. a UDT which for some
> reason doesn't seem logical to me.
>
> class X
> {
> public:
> X() {}
> ~X() {}
> };
>
> void Store()
> {
> while ( cin >> X ) // implicit call to the conversion operator
> void* operator()
> //
> }
>
> Hence if the user entered 1.5 where in 'X' is the 1.5 being stored?
>
> Here again this is logical
> double f;
> cin >> f;


If I understand you correctly, you just don't find most extractors for class
types intuitive. If you want to make the input more obviously indicate
where it is stored, then you could make operator>> more complex. For
example, you could make operator>> expect a string that contains the class
name, followed by an open parentheses, followed by the members, followed by
a close parentheses ("X(1 2 David)"). That makes the input a little more
obvious, but it also makes the function that reads it a little harder to
write. Would that seem more logical to you? In the end, what operator>>
does is entirely up to the programmer, so feel free to change its behavior
to something else (within reason).

--
David Hilsee


 
Reply With Quote
 
Old Wolf
Guest
Posts: n/a
 
      08-26-2004
http://www.velocityreviews.com/forums/(E-Mail Removed) (ma74098 wrote"

> The conversion function ios_base:perator void* () calls good() on
> its stream and returns the result.
>
> I searched Dikumware but came up short, so I'm assuming operator void*
> looks like
>
> operator void*()
> {
> return (good() ? void*(this) : 0 );
> }


In fact it can return any non-NULL value for the good case. I've
seen implementations that return (void *)1

> //// 2
> Assume input_file has the contents
> 25 130 "Sarah"
>
> class Test
> {
> public:
> Test() { } ;
> Test( int age_, int weight_, string name_)
> : Age(age_)
> , Weight(weight_)
> , Name(name_)
> { } ;
> ~Test() { };
>
> friend ostream& operator << ( ostream&, Test& );
> friend istream& operator >> ( istream&, Test& );
>
> void SaveAVec(Test &);
> vector<Test> Employ1;
>
> void WriteAllToScreen()
> {

[snipped to below]
> }
>
> private:
> int Age ;
> int Weight;
> string Name;
> };
>
> int main()
> {
> Test vec_test3;
> //Test vec_test3(25, 124, "Sarah");
> vec_test3.WriteAllToScreen();
> //cout << vec_test3;
> }
>
> Extractors - as i understand it - parse information expected by the
> destination object according to it's type. In this case the
> information (25 130 "Sarah") and the type (Test) are two unrelated
> entities, hence I'd expect the stream to fail.


What you are saying is, you would expect the function
operator<<(ostream&, Test&) to set the ostream to a fail state if
the information could not be parsed correctly.

What do you mean by "unrelated"?
25 130 "Sarah" relates to "Test" in exactly the same way
that 1.5 relates to "double" (ie. it can be parsed as it).

> The fact that that
> operator >> and subsequently the conversion operator got called for
> Employ1 object - a UDT - is somewhat of a mystery to me.


Me too, your code declares:
friend ostream& operator << ( ostream&, Test& );
friend istream& operator >> ( istream&, Test& );
but never implements them. You should get a linker error.

If you did implement these functions, then they would be called
whenever you went:
cout >> Employ1
because that is just another way of writing: operator>>(cout, Employ1)

> It further
> leads me to believe that the Employ1 looks like Test Employ1(25, 130,
> "Sarah").


It does

> Where have I gone wrong?
> Test Employ1;


Employ1 is of type "Test", so it must have a Name, Age and Weight.
Your code does not give any values to these in the default
constructor, so Employ1.Age, etc. have indeterminate values...

> while (in >> Employ1)


Now Employ1 will have values as assigned by the function
operator>>(istream&, Test&). If that function failed, then
Employ1 will have indeterminate values still.

> InVec.push_back(Employ1);


>
> This makes sense to me
> double f;
> cin >> f;
>
> assume f's input was 1.5. Now data and type match.


cin >> f would succeed if data and type matched, and fail if
they didn't match (eg. if f's input was "hello").

There is no difference between the 'double' example
and the 'Test' example. What is your problem exactly?

> An aside: I realize the 'correct way' would be along the lines of ...
>
> istream& operator >> ( istream& is, Test& rhs )
> {
> //cout << " istream& >>";
> is >> rhs.Age;
> is >> rhs.Weight;
> is >> rhs.Name;
>
> return is;
> }


This isn't really an "aside", you need to have these functions
present or your code won't even compile correctly.
 
Reply With Quote
 
Old Wolf
Guest
Posts: n/a
 
      08-26-2004
(E-Mail Removed) (ma74098 wrote:
>
> I dont have a problem with reading the data from the file. My issue
> where the data is being inserted/stored. ie. a UDT which for some
> reason doesn't seem logical to me.


A UDT is just a collection of builtin types, and functions.
Anything you can do for a normal 'double', you can do for a
'double' which is a member of a UDT.

> class X
> {
> public:
> X() {}
> ~X() {}
> };
>
> where in 'X' is the 1.5 being stored?
>


In your example, X has no member variables so it is not possible
to store anything in it. You can still have an extraction operator
for X, but it would have to do other actions (eg. do nothing, or
display the value on the screen).

> void Store()
> {
> while ( cin >> X ) // implicit call to the conversion operator
> void* operator()
> //
> }


This is nothing to do with operator void*

The expression "cin >> x" means to call this function:
std::istream &operator>>(std::istream&, X &)
like this:
operator>>(cin, x)
If you have not defined this function then the code will not
compile. If you have defined the function, then that function
reads in some data from the istream and does something with it
(which could be, storing it in one of x's members).

Then, the construct " while ( foo ) " means to evaluate foo
as a bool, and if it is true, do the step in the loop.
In this case "foo" is a "std::istream &" that was returned by
operator>> above. Only now is the conversion to void* operator
(and then the implicit conversion from void* to bool) invoked --
well after the processing and storing of cin's data has been
completed.

This is all exactly identical in concept to:

class X {
public: double f;
};

bool bar(std::istream &is, X &x)
{ is >> x.f; } // logical, right?

while( bar(cin, x) )
{ // do stuff..
 
Reply With Quote
 
ma740988
Guest
Posts: n/a
 
      08-26-2004
(E-Mail Removed) (Old Wolf) wrote in message news:<(E-Mail Removed). com>...

[...]
>
> The expression "cin >> x" means to call this function:
> std::istream &operator>>(std::istream&, X &)
> like this:
> operator>>(cin, x)
> If you have not defined this function then the code will not
> compile. If you have defined the function, then that function
> reads in some data from the istream and does something with it
> (which could be, storing it in one of x's members).


Got it.
I sense it's time for me to revisit the operator overloading and it's
various use, especially T operator() and operator T(). I suspect both
forms may take time getting used to.


Thanks to you and david.
 
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
'new' operator for built-in types? Daniel Norden Javascript 11 11-04-2008 10:34 PM
Stream operator in namespace masks global stream operator mrstephengross C++ 3 05-10-2007 07:02 AM
mapping of XML types to C/C++ built-in types Alona XML 2 04-05-2007 08:00 AM
Can inserter/extractor operator overrides be made run-time polymorphic? Randy C++ 23 01-13-2006 09:51 PM
Web Extractor =?Utf-8?B?VmlqYXk=?= ASP .Net 0 04-08-2004 10:31 AM



Advertisments