Reputation: 9519
I'm interested in improving my understanding of how to avoid writing a C++ class that causes problems when copied.
In particular, I've written a class named Policy
that I intend to copy. I have not defined a non-default destructor, copy constructor, or copy assignment operator. The only operator I've overloaded is the following:
friend bool operator== (const Policy& p1, const Policy& p2) {
for(int i=0; i<p1.x.size(); i++) {
if(p1.x[i] != p2.x[i])
return false;
}
return true;
}
The class's members are either standard data types such as int
, double
, bool
, std::string
, std::vector<double>
, std::vector<int>
, std::vector<string>
, or one of a few small (and thus not overly complex) classes I defined that are definitely copyable without any problem. Now, there is a member of Policy
that is an instance of the NRRan
class, which is a class I built as a wrapper around a non-copyable third-party data type; NRRan
is as follows:
class NRRan {
public:
double doub() { return stream->doub(); }
int intInterval(const int& LB, const int& UB) { return LB+int64()%(UB-LB+1); }
void setNewSeed(const long& seed) {
delete stream;
stream = new Ranq1(seed);
}
NRRan() { stream = new Ranq1(12345); }
~NRRan() { delete stream; }
NRRan(const NRRan& nrran) {
stream = new Ranq1(12345);
*stream = *(nrran.stream);
}
NRRan& operator= (const NRRan& nrran) {
if(this == &nrran)
return *this;
delete stream;
stream = new Ranq1(12345);
*stream = *(nrran.stream);
return *this;
}
private:
Ranq1* stream; // underlying C-struct
Ullong int64() { return stream->int64(); }
};
But the whole point of the NRRan
class is to make Ranq1
copyable. So, given the Policy
class as I've described it (sorry, I am unable to post a large part of the code), is there any thing that might cause a problem when I copy Policy
? My expectation is that copying will create a perfect value-for-value copy.
A more general way of asking my question is the following: Generally speaking, what types of things can possibly cause problems when copying a class? Is there anything in addition to the "Rule of Three" (or "Rule of Five") to be concerned about when making a class copyable?
Upvotes: 3
Views: 6534
Reputation: 5267
A class is non-copyable if it has a deleted or private copy constructor/assignment operator, or has at least one member with deleted or private copy constructor/assignment operator (applies recursively).
example:
#include <iostream>
#include <type_traits>
class A{
};
class B {
private:
A a;
B(const B&) = default;
B& operator=(const B&) = default;
public:
B() = default;
};
class NonCopyable {
int i_;
public:
NonCopyable() : i_{0}
{}
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
struct Composable {
NonCopyable nc;
};
struct C {
A a;
B b;
};
int main()
{
A a;
A aa{a}; // copy construct
A aaa = a; // copy assign
B b;
//B bb{b}; // can't
//B bbb = b; // can't
NonCopyable nc;
//NonCopyable nc2 = nc; // cannot
//NonCopyable nc3{nc}; // cannot
Composable comp;
//Composable comp2{comp}; // can't copy construct either
//Composable comp3 = comp;// can't copy assign either
std::cout << std::boolalpha;
std::cout << std::is_copy_assignable_v<A> << '\n';
std::cout << std::is_copy_assignable_v<NonCopyable> << '\n';
std::cout << std::is_copy_constructible_v<Composable> << '\n';
std::cout << std::is_copy_constructible<C>::value << '\n';
}
Output
true
false
false
false
Similarly for non-movable..
Upvotes: 0
Reputation: 2210
Well, this question is misleading..
One liner answer can be like -- use std::is_copy_constructible to find out if a class can be copied or not.
Upvotes: 2