If I want to forbid copy construction/assignment then is:
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The same as:
class foo
{
private:
foo(const foo&) = default;
foo& operator = (const foo&) = default;
};
Which is the right way and why?
The right way is the first solution : the copy constructor and assignment operators are not defined, so any attempt to use them will not compile.
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The second is declaring and defining the implicitly generated forms as private :
An object of type foo is allowed to copy itself.
Any friend class or method is also allowed to copy a foo
So copy construction/assignment is still possible.
You could also use boost::noncopyable as a base class, it does exactly that with c++11 (see the source code here)
Related
I have a library that I am trying to interface from C++ to python using pybind11.
I am finding myself in the following configuration. I have a C++ class that doesn't allow the copy (copy constructor and operator= are deleted). But this class is an output of another method. How do I allow interfacing this class in pybind11?
As an example, I want to do the interface of the class A, that I get from pybind having a pybind11/python interface:
A& foo() { ... };
With a class declaration of A that looks like that:
class A {
A (B&);
A (const A&) = delete;
A& operator= (const A&) = delete;
};
How do I manage to have a pybind11 interface of A?
Have you tried setting return_value_policy to reference?
class A {
public:
A() = default;
A (const A&) = delete;
A& operator= (const A&) = delete;
};
A& foo()
{
static A a;
return a;
}
PYBIND11_MODULE(example, m)
{
py::class_<A>(m, "A");
m.def("foo", &foo, py::return_value_policy::reference);
}
Let's say that I have this object:
struct foo {
std::unique_ptr<int> mem;
virtual ~foo() = default;
};
I can no longer return a foo object created in a function:
foo make_foo() {
foo result;
result.mem = std::make_unique<int>({});
return result;
}
As may be indicated I need the destructor to be virtual because this will be a base class. But even if I'm using the default destructor, that's not enough, I still can't return an object created in a function.
I get the error:
error C2280: foo::foo(const foo &): attempting to reference a deleted function
Is there a way to navigate around this issue?
Per [class.copy.ctor]/8
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if [...]
X does not have a user-declared destructor.
Since
virtual ~foo() = default;
is a user-declared destructor you no longer have a move constructor so it tries to use the copy constructor but can't because that is deleted as you have a non-copyable member.
To get the move constructor back, and to keep the default constructable, you need to add
foo() = default;
foo(foo&&) = default;
foo &operator=(foo &&) = default; // add this if you want to move assign as well
to foo
The reason you have to add foo() = default; when you add foo(foo&&) = default; is that foo(foo&&) = default; is a used-declared constructor and if you have any user-declared constructors then the default constructor is no longer provided.
This is a "hack" but what you could do is move the virtual destructor into another class and then inherit from that. That will give you a virtual destructor in foo without having to declare it and give you the default constructors you want. That would look like
struct make_virtual
{
virtual ~make_virtual() = default;
};
struct foo : make_virtual {
std::unique_ptr<int> mem;
};
Either provide your own copy constructor and a default constructor, convert the member to a shared pointer or provide a move constructor. One possible solution:
struct foo {
unique_ptr<int> mem;
foo() = default;
foo(const foo& copy);
virtual ~foo() = default;
};
foo::foo(const foo& copy) : mem(new int(*copy.mem)) {}
foo make_foo() {
foo result;
result.mem = make_unique<int>();
return result;
}
To disable copy constructor and assignment operator, it is clear that we could do either, since c++11:
class A {
public:
A(const A&) = delete;
A& operator=(const A&) = delete;
}
or for c++03:
class A {
private:
A(const A&);
A& operator=(const A&);
}
however, what happens with this:
class A {
private:
A(const A&) = delete;
A& operator=(const A&) = delete;
}
i guess this also leads to the same result. Is there any side effect?
It doesn't matter what access you give a deleted function - it simply doesn't exist(¹), so it is inaccessible whatever the caller.
The error messages may be slightly more confusing. See for example http:://cpp.sh/9hv7y where the first error is about "private" rather than "deleted".
¹ "it doesn't exist" is a simplification. It exists in the sense that it participates in overload resolution, but it is an error if it is the selected function. Thus
struct only_double {
only_double(intmax_t) = delete;
only_double(double arg);
};
only_double zero(0); // Error - deleted constructor called
Is there a way to disable operator= and copy constructor and allow using std::move() only?
I know that i can do
foo& operator= (const foo&) = delete;
foo(const foo&) = delete;
but this will disable std::move too.
What i want is to block copying of this class
and allow only foo foo2 = std::move(foo1);
Btw. I have private contructor.
Use defaulted special member functions:
foo(foo&&) = default;
foo& operator=(foo&&) = default;
How can I make a Class non-cloneable like we can do in Java while creating singleton.
Is there any condition we can put on copy constructor so that an exception can be thrown if user tries to make a copy of an object?
I am a novice in C++ so kindly add any info to this or redirect if an answer is already available for the same.
Just declare copy constructor and copy assign operator private
in C++03
class NonCopyable
{
public:
NonCopyable() { }
private:
NonCopyable(const NonCopyable&);
NonCopyable& operator=(const NonCopyable&);
};
Also you can make a class derive from NonCopyable, AnotherType is un-copyable
class AnotherNonCopyable : private NonCopyable
{
public:
AnotherNonCopyable () {}
}
With C++11:
class NonCopyableType
{
public:
NonCopyableType(const NonCopyableType&) = delete;
NonCopyableType& operator=(const NonCopyableType&) = delete;
};
You can delete the copy constructor and assignment operator:
struct Foo
{
Foo(const& Foo) = delete;
Foo& operator=(const Foo&) = delete;
};
If you don't have C++11 support, make them private, and don't implement them:
struct Foo
{
private:
Foo(const& Foo);
Foo& operator=(const Foo&);
};
Note In C++, class and struct are essentially the same.
Declare the copy-semantics as delete:
//C++11 only
MyClass(MyClass const &) = delete;
MyClass& operator=(MyClass const &) = delete;
That makes the class non-copyable!
//pre-C++11 code
private:
MyClass(MyClass const &); //declare only, don't define it
MyClass& operator=(MyClass const &); //declare only, don't define it
This should also work!
Is there any condition we can put on copy constructor so that an
exception can be thrown if user tries to make a copy of an object.
if you make the copy constructor private, The code will not compile when the programmer tries to make another copy. This is probably better than detecting the error with an exception at runtime.
class foo {
private:
operator = ( const foo& f);
};