Move a std::future to another std::future - c++

I'm trying to move a std::future member of class to another member of same class.
I need to do that because if I want to call std::vector.push_back(MyClass), I need to delete the copy constructor with a simple reference and create another one with double ref because my class contain a std::future member.
When i move the std::future, G++ says :
call to deleted constructor of 'std::future<int>'
_future(std::move(p_myclass._future));
note: 'future' has been explicitly marked deleted here
future(const future&) = delete
But for me, std::move returns a double ref and not a single. So I don't really know where this error comes from.
I tried the assignement operator = with double ref but doesnt work either.
class MyClass
{
private:
std::future<int> _future;
public:
MyClass(const MyClass&) = delete;
MyClass(const MyClass&&);
MyClass& operator=(MyClass &) = delete;
MyClass& operator=(MyClass &&);
};
MyClass::MyClass(const MyClass &&p_myclass) : _future(std::move(p_myclass._future)) {};
MyClass& MyClass::operator=(MyClass &&p_myclass)
{
this->_future = std::move(p_myclass._future);
return (*this);
};
Of course my std::future is initialised on main constructor, but there is no need to paste it here.
Both doesn't work.
Thanks in advice.

p_myclass is const, and then so is p_myclass._future. That's why it can't be moved from; moving from an object requires modifying it. _future(std::move(p_myclass._future)) attempts to copy it instead, but of course std::future is not copyable.

Related

Assignement operator changing value of the assigned object

I implemented a class to handle some external functions (e.g of another DLL). This functions gives me an integer I can use as a handle. Here is the important part of my code:
MyClass
{
public:
MyClass() {
handle = getHandlefromExternalFunction();
}
~MyClass {
if(handle>0)
freeHandleFromExternalFunction(handle);
}
MyClass& operator=(MyClass& other) {
freeHandleFromExternalFunction(handle);
handle = other.handle
other.handle = 0; //Is this a bad idea?
}
private:
int handle;
}
In my main function I have an object of myClass. At some point I am using the assignement operator to change the values of the object:
MyClass object;
//some code
object = MyClass();
After assignement the object created by MyClass() is immediatly destroyed since it gets out of scope. But I don't want freeHandleFromExternalFunction() to be called on that handle, since I am using it in the assigned object. Therefor I change the value of the assigned object in the assignement operator handle = 0. My question is: Is this a bad idea? Has anybody a better solution for my problem?
Yes it's a bad idea. You don't normally expect the right-hand side of an assignment to be modified.
If you want to move ownership then use the "move" assignment operator together with std::move:
MyClass& operator=(MyClass&& other) { ... }
// ...
MyClass a = ...;
MyClass b;
b = std::move(a);
If you only want movement like this (where the can be only one owner of the contained resource), then I also suggest you mark the copy-constructor and copy-assignment operators as deleted:
MyClass& operator=(MyClass const&) = delete;
MyClass(MyClass const&) = delete;
And following the rule of five don't forget the move-constructor and destructor:
~MyClass() { ... }
MyClass(MyClass&& other) { ... }
class MyClass {
public:
//....
MyClass& operator=(MyClass& other)
Non-const other in an assignment is a bad idea, and can easily surprise a programmer. Most programmers don't expect the right hand side of an assignment to be mutated.
Also this won't compile:
MyClass obj;
obj = MyClass(); // error
For this to compile you must use move semantics, which is probably what you meant from the start:
class MyClass2 {
public:
//....
MyClass2& operator=(const MyClass2& other) = delete;
MyClass2& operator=(MyClass2&& other)
The && means that the other may be emptied in the process:
MyClass2 obj, obj2, obj3;
obj = MyClass2(); // ok. Will be moved
obj2 =std::move(obj); // ok
obj3 = obj2; // error, not an rvalue rference (not MyClass2 &&)
Make sure no two objects hold the same handle. Make sure copy and assignment are deleted, and move assignment and move constructor nullify the handle of the right hand side.
Your object should own the handle. The handle should have only one owner.

The right way to return a smart pointer from a class member?

I am trying to write the singleton pattern in the person class which gives me the ability to create just one instance for that class and I can use it in any place in my program.
The following is the class:
// The declaration
class Person {
static unique_ptr<Person> instance;
Person() = default;
Person(Person&) = delete;
Person& operator=(const Person&) = delete;
~Person() = default;
public:
static unique_ptr<Person> getInstance();
};
// The implementation
unique_ptr<Person> instance = NULL;
unique_ptr<Person> Person::getInstance() {
if (instance == NULL) {
instance = unique_ptr<Person>(new Person());
}
return instance;
}
But the problem that it gives me this error: Error C2280 'std::unique_ptr<Person,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
Unfortunately, I don't understand that problem and I don't know how to solve?
The copy constructor of std::unique_ptr is implicitly deleted since it has an explicitly defined move constructor.
From the C++11 Standard, 12.8 Copying and moving class objects:
7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted ([dcl.fct.def]).
You can solve your problem by:
Returning a reference to a Person.
static Person& getInstance();
Person& Person::getInstance()
{
static Person p;
return p;
}
Returning a shared_ptr<Person>.
static std::shared_ptr<Person> getInstance();
std::shared_ptr<Person> Person::getInstance()
{
static std::shared_ptr<Person> p(new Person);
return p;
}
I recommend the first solution since it is simpler.
PS Please note that neither of them requires use of the static member variable instance.

class constructor with const reference

in this class
class Foo {
public:
Foo(){}
Foo(Foo const &) {}
};
when would Foo(Foo const &) ever be called? I do not understand this kind of constructor
This is called copy constructor. When you want to initialize a class instance by copying an existing instance, you'd probably want to use it.
const - you don't want to change the object you are copying.
reference - you don't want to copy the existing instance into the constructor, just to copy it again in the initialization.

Reset an object

Lately I often reset an object by assigning a new value to it with operator=. Most of my classes have a copy constructor and operator= defined using "copy and swap" idiom. Which works fine in most cases, albeit not as efficient as it could be, but that mostly does not matter. There is one case that this does not work though. Its when the destructor needs to be called before the constructor of the new object.
Note: most of the classes for which I use this are uncopyable
class Foo
{
public:
Foo() : m_i(0) {}
Foo(int i) : m_i(i) {}
Foo(Foo&& rhs);
Foo& operator=(Foo rhs);
friend void swap(Foo& lhs, Foo& rhs);
private:
Foo(Foo& rhs) {} // uncopyable object
int m_i;
};
Foo::Foo(Foo&& rhs)
: Foo()
{
swap(*this, rhs);
}
Foo& Foo::operator=(Foo rhs)
{
swap(*this, rhs);
return *this;
}
void swap(Foo& lhs, Foo& rhs)
{
using std::swap;
swap(lhs.m_i, rhs.m_i);
}
int main()
{
Foo f(123);
f = Foo(321); // at one time both Foo(123) and Foo(321) exist in memory
}
I have then taught to maybe rewrite operator= to first manually call the destructor and then do the swap (in this case rhs would be taken by const reference). However this answer on stackOverflow made me think otherwise.
I really like operator= to reset my objects, becuase the code is clean and is the same as for built in types (like int). It also uses both the code from constructor and destructor, so no extra code needs to be written and maintained.
So my question is: Is there a way to achieve my goal to reset my object with clean code and no extra code to be written and have the object be destructed before the new one is constructed?
By definition, if you assign a new value to an old object, the new value has been constructed before the assignment can take place.
Your 'old object' is not really destructed, either.
So No. There is no way. And there shouldn't: you shouldn't redefine the 'obvious' behavior of the assignment operator.
But placement new could help here apart from the tilde and exotic construction syntax, maybe this code approaches 'clean' :)
Foo old(a, b, c);
old.~Foo(); // explicit destruction
new (&old) Foo(d, e, f);
If you have code in the constructor that needs to also be called by the assignment operator, then put that code in a private member function and call that from both the destructor and the assignment operator.
You object won't be destructed (and you don't want it to be really), but it will do the same thing as the destructor.

Not copyable object and exception in copy constructor and operator=

I'd like to make object of class not copyable so I put copy constructor and operator= in private section. However one class is friend of this class so it has access to private methods. Is it good idea to put throw exception in copy constructor and operator= to be sure that object will not be copied?
One approach to make it not copyable is just to declare the copy constructor, but don't implement it at all. That will force a linker error at compile time if anyone tries to use it.
class foo
{
private:
foo(const foo&); // not defined
foo& operator=(const foo&); // not defined
};
#Mysticial have answered this question which is usually done in C++03. But in C++11, you can do this, more nicely:
class foo
{
private:
foo(const foo&) = delete;
foo& operator=(const foo&) = delete;
};
The =delete conveys the message that foo doesn't support copy-semantic, as it has been disabled by explicitly marking it with delete. I've explained this in detail here:
Is there a way to disable constructor synthesizing on a class?