Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my fstream being implicitly deleted?

I'm working with a few HID devices, all of which have classes deriving from the following base class (in main.h):

class HIDDevice {
    public:
        hid_device *device;

        virtual void read(std::fstream)=0;
        virtual void write(std::fstream)=0;
};

Here's one of the device classes deriving from it (device.h):

class MyDevice : public HIDDevice {
    public:
        void read(std::fstream);
        void write(std::fstream);
};

...and a sample of the implementation:

void MyDevice::read(std::fstream file) {
    // Read from card and write to file
    response = send_command(READ_DEVICE);
    file.write((char *)&response[0], response.size());
}

...and the caller:

fstream file (filename, ios::binary | ios::in);
dev->read(file);

When I try and compile, I get the following error:

main.cpp:294:27: error: use of deleted function ‘std::basic_fstream::basic_fstream(const std::basic_fstream&)’
In file included from source/main.cpp:24:0: /usr/include/c++/4.6/fstream:761:11: error: ‘std::basic_fstream::basic_fstream(const std::basic_fstream&)’ is implicitly deleted because the default definition would be ill-formed:

... and I have no idea why, probably because I'm fairly new to C++ and I've done something idiotic.

Changing the arguments back to references (using &), I get the following error:

/main.o:(.rodata._ZTV13MyDevice[vtable for MyDevice]+0x18): undefined reference to `MyDevice::write(std::basic_fstream >&)'

Can anyone help me fix this problem?

like image 463
Andy E Avatar asked Sep 14 '12 22:09

Andy E


3 Answers

Try tossing those std::fstreams around by reference.

class MyDevice : public HIDDevice {
    public:
        void read(std::fstream&);
        void write(std::fstream&);
};
like image 183
WhozCraig Avatar answered Nov 19 '22 10:11

WhozCraig


Just for reference, I had the same compiler error, but created it in a different way that wasn't immediately obvious to me. Out of habit I wrote:

auto stream = fstream(output, iOS::out | iOS::binary);

Which, of course, creates a temporary fstream object and copies it to stream. That worked in Xcode 6 using clang, but not for GCC 4.9.2.

like image 5
Aaron Burghardt Avatar answered Nov 19 '22 10:11

Aaron Burghardt


The HIDDevice method signatures mean that the fstreams are being passed around by value. This in turn means that copies of the original stream objects have to be created at the call site using the copy constructor. It is this copy constructor that has the canonical signature std::basic_fstream::basic_fstream(const std::basic_fstream&).

The compiler is telling you that for some reason (which has to do with the particulars of the basic_fstream implementation your standard library uses) it cannot auto-generate this copy constructor, hence it cannot fulfill your implicit command to make copies of the streams.

As others have already said, the usual modus operandi (which will also prevent the error here) is to pass the arguments by reference instead of by value.

like image 3
Jon Avatar answered Nov 19 '22 11:11

Jon