operator void* , stream extractor and built in types

Discussion in 'C++' started by ma740988, Aug 25, 2004.

  1. ma740988

    ma740988 Guest

    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;
    }
    ma740988, Aug 25, 2004
    #1
    1. Advertising

  2. ma740988

    David Hilsee Guest

    "ma740988" <> wrote in message
    news:...
    > 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.

    --
    David Hilsee
    David Hilsee, Aug 25, 2004
    #2
    1. Advertising

  3. ma740988

    ma740988 Guest

    "David Hilsee" <> 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;
    ma740988, Aug 25, 2004
    #3
  4. ma740988

    David Hilsee Guest

    "ma740988" <> wrote in message
    news:...
    <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
    David Hilsee, Aug 26, 2004
    #4
  5. ma740988

    Old Wolf Guest

    (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.
    Old Wolf, Aug 26, 2004
    #5
  6. ma740988

    Old Wolf Guest

    (ma740988) 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..
    Old Wolf, Aug 26, 2004
    #6
  7. ma740988

    ma740988 Guest

    (Old Wolf) wrote in message news:<>...

    [...]
    >
    > 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.
    ma740988, Aug 26, 2004
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ollej Reemt
    Replies:
    7
    Views:
    518
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    786
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    824
    S.Tobias
    Jul 22, 2005
  4. mrstephengross
    Replies:
    3
    Views:
    396
    James Kanze
    May 10, 2007
  5. Replies:
    1
    Views:
    402
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page