user2980207
user2980207

Reputation: 293

Using vectors with classes that contain non-copyable data types

My issue is that I have a class which contains a std::ifstream, std::ofstream, and std::mutex. None of these objects can be directly copied as shown in the example below.

std::ifstream stream1;
std::ifstream stream2;
stream1 = stream2; //<-Compiler Error!

My problem is not that I want to copy any instances of my class, but that the push_back() function in vectors is trying to call the copy constructor for my class. I have designed an example that replicates my issue and pasted it below.

#include <fstream> //for std::ifstream // std::ofstream
#include <vector> //for std::vector
#include <mutex> //for std::mutex

class MyClass
{
public:
    MyClass(int ID) : ID(ID) { }
    std::ofstream outputstream;
    std::ifstream inputstream;
    std::mutex mymutex;
private:
    int ID;
};

int main()
{
    std::vector<MyClass> MyVector;
    MyVector.push_back(MyClass(1)); //<-- Error C2280 'MyClass::MyClass(const MyClass &)': attempting to reference a deleted function

    return 0;
}

I am having issues trying to figure out how to get around this error. Any help would be greatly appreciated. Keep in mind, I will never be directly calling the copy constructor as I have no need in my actual scenario to ever copy an instance of this class, but it seems that push_back is calling it and I have been unsuccessful in my attempts to override it.

Edit: I think one way to fix it would be to use pointers instead of ifstream,ofstream, and mutex objects but I would prefer to avoid this at all costs.

Upvotes: 9

Views: 1857

Answers (3)

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

The real problem here is that this class contains a std::mutex member. Which cannot be copied/moved. This means that classes that have mutex members don't like to live inside vectors.

You need a custom copy and/or move constructors, for your class, and implement the appropriate semantics to copy the streams, and figure out what you want to do with the mutex.

Upvotes: 5

Robert Pr&#233;vost
Robert Pr&#233;vost

Reputation: 1707

Since you have access to C++11 features, you could use emplace_back to construct the element in place.

MyVector.emplace_back(1);

However, there is some problem with std::mutex. This member has to be a pointer in order for the above to work. Otherwise, you could change all the elements of the class to be types that are copyable (e.g., pointers).

Upvotes: 3

user2985792
user2985792

Reputation:

You might try using a vector of pointers to your objects. It is better to use some kind of smart pointer, rather than a vector of raw pointers.

i.e. std::vector< std::shared_ptr< MyClass >> MyVector;

now you have a container of pointers to MyClass objects.

Upvotes: 4

Related Questions