operator void* , stream extractor and built in types

M

ma740988

The conversion function ios_base::eek: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;
}
 
D

David Hilsee

ma740988 said:
The conversion function ios_base::eek: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.
 
M

ma740988

David Hilsee said:
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;
 
D

David Hilsee

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).
 
O

Old Wolf

(e-mail address removed) (ma740988) wrote"
The conversion function ios_base::eek: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.
 
O

Old Wolf

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..
 
M

ma740988

(e-mail address removed) (Old Wolf) wrote in message
[...]
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top