Home > Software engineering >  Use of deleted function when using fstream
Use of deleted function when using fstream

Time:05-03

I'm receiving the message "Use of deleted function" when I combine the use of an ofstream (which I later want to use to record information) and the placement of one class inside another. Here is my minimal example:

#include <iostream>
#include <unistd.h>
#include <fstream>

class Tracker {
    private:
        std::ofstream tracker_file;
    public:
        Tracker(const std::string filename) {
            tracker_file.open("tracker_file.csv", std::ios_base::app);
        }
};

class Penguin {
    private:
        Tracker p_tracker;
    public:
        Penguin(
            Tracker p_tracker
        ) : p_tracker(p_tracker) {}
};

int main()
{
    Tracker penguin_tracker = Tracker("output");
    Penguin gentoo(penguin_tracker);
    return 1;
}

I don't understand how these are related, but if I remove the intermediate class then it works, and if I remove the ofstream it works.

CodePudding user response:

In this line in the ctor of Penguin:

) : p_tracker(p_tracker) {}

You attempt to initalize the Tracker p_tracker data member. Since you pass it an existing Tracker instance, it attempts to use the copy constuctor.

But class Tracker does not have a copy constructor. This is the "deleted function" mentioned in the error you got.

As @NathanPierson wrote in the comment below, this is because of the deleted copy constructor of the std::ofstream member variable tracker_file (and not because of the converting constructor you defined, as I originally wrote).

You could have theoretically solved it by adding a copy ctor to Tracker, something like:

Tracker(Tracker const & other)
{
    // ...
}

However - as mentioned above class Tracker has a std::ofstream member which is non copyable.

So the question is what did you mean should happen in this case ?

On a side note: using the same name: p_tracker for both the class data member and the parameter passed to the constructor is a bit confusing and not recomended.

UPDATE: To answer the question of the OP in the comment below: If class Penguin only needs to keep a refernce to a Tracker instance, you can do the following (added "m_" prefix to members to diffrentiate them from other variables):

#include <iostream>
#include <fstream>

// No change in Tracker:
class Tracker {
private:
    std::ofstream m_tracker_file;
public:
    Tracker(const std::string filename) {
        m_tracker_file.open("tracker_file.csv", std::ios_base::app);
    }
};

// Penguin now holds a reference to Tracker:
class Penguin {
private:
    Tracker & m_tracker;
public:
    Penguin(
        Tracker & tracker
    ) : m_tracker(tracker) {}
};

int main()
{
    Tracker penguin_tracker("output");
    Penguin gentoo(penguin_tracker);
    return 0;
}

However - this solution requires you to ensure the Tracker penguin_tracker is alive as long as Tracker penguin_tracker is alive (otherwise you will have a dangling reference). In your example it is OK, just mentioned in for the general case.

Another side note: main should return 0 if all went well (not 1). See: What should main() return in C and C ?.

  •  Tags:  
  • c
  • Related