user4643144
user4643144

Reputation:

unable to overload ofstream operator due to - cannot bind to value of unrelated type (stroustrup c++ chapter 10)

Background:

I am working my way though Stroustrup's c++ book. I am on chapter 10 completing the drills and come across a problem. Now, as far as I can tell I am not strictly following the book, based on how I have seen others answer the questions. I guess Im just after a little more understanding on how to implement the code.

My general aim is to have a write function rather than have it in main().

The aim of the following function is to return an ofstream.

ofstream& c_data_file()
{
    string oname = "mydata.txt";
    ofstream ost {oname};
    if (!ost) {
        string error = "cannot open " + oname;
        throw runtime_error(error);
    }
    return ost;
}

This code does come with a warning from the compiler and I am including it, as it may be related to the problem. The warning is:

Reference to stack memory associated with local variable 'ost' returned

ostream& operator<<(ostream& os, const Point& p)
{
    return os << "(" << p.x <<"," <<p.y <<")";
}

ofstream& operator<<(ofstream& ost, const Point& p)
{
    return ost << "(" << p.x <<"," <<p.y <<")";
}

the ostream works fine (i use this stream else where). The ofstream does not work, returning the error:

Non-const lvalue reference to type 'ofstream' (aka 'basic_ofstream') cannot bind to a value of unrelated type 'basic_ostream >'

The following is the rest of the relevant code:

int main() {

    vector<Point> original_points;
 ofstream& ost = c_data_file();
    for (int i = 0; i<original_points.size(); i++) {
        ost << original_points[i] << "\n";
    }
    ost.close();
}

I have been looking online all day, the following question seems the closet:

overloaded operator << on ofstream concatenation problems

However, i find it hard to understand the answer and from what i do understand it does not solve my issue.

Thank you for reading and for any help you can give.

I am including the following edit here as well as my response to iksemyonov with the hope to clearly express the problem for everyone. Edit1: The warning was resolved following advice from TBBle. The main issue still stands, as the link indicates and iksemyonov suggests I should use ostream instead of ofstream. This is problematic. Ostream is (following the book) used to send data to cout which is what i am doing (code not present). I also want to send the same data to a file (ideally as the book suggests via ofstream).

Edit 2: following the link and iksemyonov's suggestions worked. A number of the comments below helped me execute the suggestions. So thank you to everyone who commented.

Upvotes: 0

Views: 265

Answers (3)

iksemyonov
iksemyonov

Reputation: 4196

Based on the link provided by OP,

overloaded operator << on ofstream concatenation problems

other than fixing the returning reference to temporary error, the fix is to change

ofstream& operator<<(ofstream& ost, const Point& p)
{
    return ost << "(" << p.x <<"," <<p.y <<")";
}

to

ostream& operator<<(ostream& ost, const Point& p)
{
    return ost << "(" << p.x <<"," <<p.y <<")";
}

which compiles just fine. As the answer in the link describes, the reason for the error to occur is that ost << "(" returns an object of type ostream, and the further calls to operator<< thus fail because of the incompatibility reported by the compiler.

On a side note, it is not a good style to not return an exit code from main, as in return 0.

Upvotes: 1

TBBle
TBBle

Reputation: 1476

You have created an local ofstream in your function, so you can't return a reference to it, as it's gone after your function ends.

So you have to return an ofstream object instead.

You can't copy streams, so it'll have to be a move. Luckily, that'll be automatic in this case. (Assuming C++11. If not, you need to restructure your code).

And if you're on gcc before gcc 5, you can't move streams due to a bug.

So the simplest change to your function is:

ofstream c_data_file()
{
    string oname = "mydata.txt";
    ofstream ost {oname};
    if (!ost) {
        string error = "cannot open " + oname;
        throw runtime_error(error);
    }
    return ost;
}

and the caller becomes

ofstream ost = c_data_file();

Upvotes: 1

Jts
Jts

Reputation: 3527

ofstream& c_data_file() is returning a reference (&) to an ofstream ost; which no longer exists (ofstream ost; is a local object and is gonna be destroyed once it goes out of scope)

so what you could do instead is modify your function to ofstream c_data_file() and this way you will no longer return a temporary object.

Upvotes: 0

Related Questions