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);
}
Related
This is a very simple example with class A and B.
I want allow only deep copy, so I disabled the rvalue reference constructor.
#include <iostream>
class B;
class A {
public:
A();
~A();
A(const A & other);
A& operator=(const A & other);
A(A && ) = delete;
A& operator=(A && ) = delete;
B toB() const;
private:
int a_;
};
class B {
public:
B();
~B();
B(const B & other);
B& operator=(const B & other);
B(B && ) = delete;
B& operator=(B && ) = delete;
A toA() const;
private:
int b_;
};
A::A()
{
}
A::~A()
{
}
A::A(const A & other)
: a_(other.a_)
{
}
A& A::operator=(const A & other)
{
a_ = other.a_;
return *this;
}
B A::toB() const
{
return B();
}
B::B()
{
}
B::~B()
{
}
B::B(const B & other)
: b_(other.b_)
{
}
B& B::operator=(const B & other)
{
b_ = other.b_;
return *this;
}
A B::toA() const
{
return A();
}
int main()
{
A a();
B b();
return 0;
}
the gcc compiler report bugs like this:
In member function 'B A::toB() const':
error: use of deleted function 'B::B(B&&)'
return B();
^
note: declared here
B(B && ) = delete;
I'm wandering why it use B(B && ) function, not the B(const B &) function instead.
Because you added the move-constructor. Deleted but declared functions are still part of the interface of a class. That means it will be considered by the compiler, but since it's marked as deleted you get the error. If you want to force the copy-constructor to be called then remove the move-constructor declaration.
From this deleted functions reference:
Any use of a deleted function is ill-formed (the program will not compile). This includes calls, both explicit (with a function call operator) and implicit (a call to deleted overloaded operator, special member function, ...
[Emphasis mine]
Since the deleted functions are part of the interface, the compiler will try to use them. So when there is a deleted move constructor, the compiler will see that and try to use it, but since it is deleted there will be an error.
Since no move constructor will be created by the compiler if there is an explicit copy constructor (as per this move constructor reference) simply having a defaulted copy constructor will inhibit moving of object.
All of that means your classes can be very much simplified:
class A {
public:
A() : a_() {}
A(const A & other) = default;
B toB() const;
private:
int a_;
};
class B {
public:
B() : b_() {}
B(const B & other) = default;
A toA() const;
private:
int b_;
};
Because the classes above have user-declared copy constructors no movement constructor will be created, and the class can't be moved only copied.
Move Constructor would be called whenever a nameless object is created.
In B A::toB() const function there is a statement return B(); which creates a nameless object to be returned from the function. For creating a nameless object move constructor is required which is deleted.
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)
I have a surprising issue in VS2010.
This is the header.h of my main.cpp
class A;
class B;
class A
{
public:
double x,y;
A();
~A();
A(const A &obj);
A(const B &obj);
A& operator=(const A &obj);
};
class B
{
public:
double x,y;
B();
~B();
B(const B &obj);
B& operator=(const B &obj);
};
The main.cpp is containing the declaration of methods and :
#include "header.h"
#include <iostream>
int main() {
A t;
B u;
A a(u);
t=u;
return 0;
}
As you can see, to do
A a(u);
I had to add this method
A(const B &obj);
But for
t=u;
It uses
A& operator=(const A &obj);
Why I don't get an error ?
If you want to avoid this, you should mark your "A from B" constructor as explicit:
explicit A(const B &obj);
Any constructor not marked as explicit will be used by the compiler for implicit conversions.
by adding A(const B &obj); you provided a way to convert B to A, which is used in t=u; so the compiler can do what you ask and no error is needed. The conversion can be done because the parameter const A &obj allows conversion.
If, for whatever reason, the A(const B &obj) is meaninful but you also want t=u to fail then you have to disable implicit type conversion using the explicit keyword.
This means that only when you specifically cast B as an instance of A will the conversion be performed.
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);
};
Suppose I have a class with a factory method
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
}
Is it possible to prevent the instantiation of an object of this class with a new, so that factory method is the only method to create an instance of the object?
Sure; just make the constructor private (protected if this is a base class):
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // Default constructor
};
You should make the copy constructor private/protected as well, if required.
And as always, you should strongly consider returning a smart pointer rather than a raw pointer, in order to simplify memory management issues.
You may also want to make the copy constructor private as well or with new C++11 syntax you can explicitly tell the compiler to not copy it and make the default constructor private with something like this:
struct NonCopyable {
NonCopyable & operator=(const NonCopyable&) = delete;
NonCopyable(const NonCopyable&) = delete;
NonCopyable() = default;
};
class A : NonCopyable {
public:
static std::shared_ptr<A> newA()
{
// Some code, logging, ...
return std::make_shared<A>();
}
private:
A() {} // Default constructor
};
The C++03 way was usually something like this:
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // no outsider default constructor
A(const A& rhs); // no copy
A& operator=(const A& rhs); // no assignment
};
int main()
{
A x; // C2248
A y(x); // C2248
x = y; // C2248
A* p = A::newA(); // OK
std::cin.get();
return 0;
}