I faced a situation where I want this kind of function:
MoveOnly createMoveOnly();
Stored here:
std::function<boost::any ()> factory = &createMoveOnly;
This should work, AFAIK, because MoveOnly is convertible to boost::any
Using boost 1.55 which supports move semantics for boost.any, it does not work. It triggers an error about trying to use the deleted copy constructor for MoveOnlyinternally in the holder for boost::any. But the top-level constructor for Boost.Any is correctly chosen (It uses a templated ValueType && that forwards parameters).
Maybe the problem is in std::function.
Any hints?
I think that boost::any requires a copy constructor and assignment operator. The documentation seems to indicate this:
As the emphasis of a value lies in its state not its identity, values can be copied and typically assigned one to another, requiring the explicit or implicit definition of a public copy constructor and public assignment operator. Values typically live within other scopes, i.e. within objects or blocks, rather than on the heap. Values are therefore normally passed around and manipulated directly as variables or through references, but not as pointers that emphasize identity and indirection.
http://www.boost.org/doc/libs/1_55_0/doc/html/any/reference.html
Related
Have found comparable questions but not exactly with such a case.
Take the following code for example:
#include <iostream>
#include <string>
#include <vector>
struct Inner
{
int a, b;
};
struct Outer
{
Inner inner;
};
std::vector<Inner> vec;
int main()
{
Outer * an_outer = new Outer;
vec.push_back(std::move(an_outer->inner));
delete an_outer;
}
Is this safe? Even if those were polymorphic classes or ones with custom destructors?
My concern regards the instance of "Outer" which has a member variable "inner" moved away. From what I learned, moved things should not be touched anymore. However does that include the delete call that is applied to outer and would technically call delete on inner as well (and thus "touch" it)?
Neither std::move, nor move semantics more generally, have any effect on the object model. They don't stop objects from existing, nor prevent you from using those objects in the future.
What they do is ask to borrow encapsulated resources from the thing you're "moving from". For example, a vector, which directly only stores a pointer some dynamically-allocated data: the concept of ownership of that data can be "stolen" by simply copying that pointer then telling the vector to null the pointer and never have anything to do with that data again. It's yielded. The data belongs to you now. You have the last pointer to it that exists in the universe.
All of this is achieved simply by a bunch of hacks. The first is std::move, which just casts your vector expression to vector&&, so when you pass the result of it to a construction or assignment operation, the version that takes vector&& (the move constructor, or move-assignment operator) is triggered instead of the one that takes const vector&, and that version performs the steps necessary to do what I described in the previous paragraph.
(For other types that we make, we traditionally keep following that pattern, because that's how we can have nice things and persuade people to use our libraries.)
But then you can still use the vector! You can "touch" it. What exactly you can do with it is discoverable from the documentation for vector, and this extends to any other moveable type: the constraints emplaced on your usage of a moved-from object depend entirely on its type, and on the decisions made by the person who designed that type.
None of this has any impact on the lifetime of the vector. It still exists, it still takes memory, and it will still be destructed when the time comes. (In this particular example you can actually .clear() it and start again adding data to a new buffer.)
So, even if ints had any sort of concept of this (they don't; they encapsulate no indirectly-stored data, and own no resources; they have no constructors, so they also have no constructors taking int&&), the delete "touch"ing them would be entirely safe. And, more generally, none of this depends on whether the thing you've moved from is a member or not.
More generally, if you had a type T, and an object of that type, and you moved from it, and one of the constraints for T was that you couldn't delete it after moving from it, that would be a bug in T. That would be a serious mistake by the author of T. Your objects all need to be destructible. The mistake could manifest as a compilation failure or, more likely, undefined behaviour, depending on what exactly the bug was.
tl;dr: Yes, this is safe, for several reasons.
std::move is a cast to an rvalue-reference, which primarily changes which constructor/assignment operator overload is chosen. In your example the move-constructor is the default generated move-constructor, which just copies the ints over so nothing happens.
Whether or not this generally safe depends on the way your classes implement move construction/assignment. Assume for example that your class instead held a pointer. You would have to set that to nullptr in the moved-from class to avoid destroying the pointed-to data, if the moved-from class is destroyed.
Because just defining move-semantics is a custom way almost always leads to problems, the rule of five says that if you customize any of:
the copy constructor
the copy assignment operator
the move constructor
the move assignment operator
the destructor
you should usually customize all to ensure that they behave consistently with the expectations a caller would usually have for your class.
As I read some articles, rvalue references and move semantics are usually described together. However as I understand, rvalue references are just references to rvalues and have nothing to do on their own with move semantics. And move semantics could be implemented probably without even using rvalue references. So the question is, why move constructor/operator= use rvalue references? Was it just to make it easier to write the code?
Consider the problem. There are two basic move operations we want to support: move "construction" and move "assignment". I use quotations there because we don't necessarily have to implement them with constructors or move assignment operators; we could use something else.
Move "construction" means creating a new object by transferring the contents from an existing object, such that deleting the old object doesn't deallocate resources now used in the new one. Move "assignment" means taking a pre-existing object and transferring the contents from an existing object, such that deleting the old object doesn't deallocate resources now used in the new one.
OK, so these are the operations we want to do. Well, how to do it?
Take move "construction". While we don't have to implement this with a constructor call, we really want to. We don't want to force people to do two-stage move construction, even if it's behind some magical function call. So we want to be able to implement movement as a constructor. OK, fine.
Here's problem 1: constructors have no names. Therefore, you can only differentiate them based on argument types and overloading resolution. And we know that the move constructor for an object of type T must take an object of type T as a parameter. And since it only needs one argument, it therefore looks exactly like a copy constructor.
OK, so now we need some way to satisfy overloading. We could introduce some standard library type, a std::move_ref. It would be like std::reference_wrapper, but it would be a distinct type. Therefore, you could say that a move constructor is a constructor that takes a std::move_ref<T>. Alright, fine: problem solved.
Only not; we now have new problems. Consider this code:
std::string MakeAString() { return std::string("foo"); }
std::string data = MakeAString();
Ignoring elision, C++11's expression value category rules state that a type which is returned from a function by value is an prvalue. And therefore, it will automatically be used by move constructors/assignment operators wherever possible. No need for std::move or the like.
To do it your way would require this:
std::string MakeAString() { return std::move(std::string("foo")); }
std::string data = std::move(MakeAString());
Both of those std::move calls would be needed to avoid copying. You have to move out of the temporary and into the return value, and then move out of the return value and into data (again, ignoring elision).
If you think that this is merely a minor annoyance, consider what else rvalue references buy us: perfect forwarding. Without the special reference-collapsing rules, you could not write a proper forwarding function that forwards copy and move semantics perfectly. std::move_ref would be a real C++ type; you couldn't just slap arbitrary rules like reference collapsing onto it like you can with rvalue references.
At the end of the day, you need some kind of language construct in place, not merely a library type. By making it a new kind of reference, you get to be able to define new rules for what can bind to that reference (and what cannot). And you get to define special reference-collapsing rules that make perfect forwarding possible.
The connection is that it is safe to move from an rvalue (because (in the absence of casts) rvalues refer to objects that are at the end of their lifespans), so a constructor that takes an rvalue reference can be safely implemented by pilfering/moving from the referenced object.
From a C++-language point of view, this is the end of the connection, but the standard library further expands on this connection by consistently making construction from lvalues copy and construction from rvalues move, and by providing helper functions (such as std::move) which make it straightforward to chose whether to move or copy a particular object (by changing around the value category of the object in the expression that causes the copy/move).
Move semantics can be implemented without rvalue-references, but it would be a lot less neat. A number of problems would need to be solved:
How to capture an rvalue by non-const reference?
How to distinguish between a constructor that copies and a constructor that moves?
How to ensure that moves are used wherever they would be a safe optimization?
How to write generic code that works with both movable and copyable objects?
I know std::queue::pop() returns void. For two reasons:
exception safety: something might throw after removing the element
to be able to return the value by reference
Fine.
Now if I understand the new C++11 move semantics correctly, the second is no longer a valid argument.
So... the only thing preventing std::queue to have a pop-like function returning the value lies in the possibility that the move constructor throws?
I have a hard time thinking of situations where such a move constructor would throw. Who knows of an example?
I guess the same goes for std::stack::pop(), std::vector::pop_front(), std::vector::pop_back(), std::deque::pop_front(), std::deque::pop_back(), std::list::pop_front(), std::list::pop_back() and what not.
There aren't many cases where std::move() can throw in the standard library but there are cases. For example, if the container uses a stateful allocator, its children also use this allocator, but it won't be moved to a result: this would rather get a default constructed version of an allocator (if I remove correctly). Given that the allocators are stateful this means that the object can't be moved and thus the move construction fails with an exception. Why does this type then have a move constructor? Well, because it might be instantiated with non-stateful allocator in which case moving won't throw. In addition, once we move to user defined classes we have no idea under which condition moving them might throw.
Using clever SFINAE techniques it would indeed be possible to have an atomic non-throwing pop_and_move() for just datatypes that implement no-throwing move or no-throwing copy.
There is even a noexcept() construct available to see if something might throw.
One of the new concepts in C++11 in particular that extends SFINAE is that if the body doesn't compile the function doesn't exist. Thus one could implement based on noexcept().
I would say for backward compatibility the function would need a new name, which therefore allows it to co-exist with the existing functionality of calling them separately, not breaking containers of types that do not have the semantics to allow it.
Another problem is, that not every class really benefits from moving, i.e., they might only have a copy ctor.
struct DontLikeMoves{
// some data, whatever...
DontLikeMoves(DontLikeMoves const& other){
// might throw, who knows!
// and this will even get called for rvalues
}
};
When is a class implicitly copied in C++?
I have a class that contains a unique_ptr, and therefore cannot be safely copied, and therefore, I disabled the copy constructor on the class by creating private versions of X(X&) and X& operator = X&.
I immediately ran into the problem that instances of this class cannot be returned, because returning actually makes a copy of the instance.
Are there any other situations I need to watch out for?
Returning does not copy the instance, it moves the instance. You just forgot to provide a move constructor. In addition, classes are now moved when used in Standard containers in most situations in which they used to be copied.
In short, provide a move constructor and move assignment operator (and swap, preferably) and you should find that almost all situations where copies are implicit, they're now moves.
The situations that come to mind are: functions that receives the class by value, functions that returns then class by value, and any class or container that contains that class. Classes like std::vector will use move semantics whenever possible (you did overload that right)? but will be unable to use functions that require a copy constructor, such as copying the vector. As GMan said though, you can make a copy constructor for your class, and do a deep copy of the std::unique_ptr manually, if you want to make things easier.
I can't use shared_ptr in my project, no boost :(
So, I'm having a class roughly similar to the one below:
class MyClass
{
private:
std::auto_ptr<MyOtherClass> obj;
};
Now, I want to store the instances of above class in std::vector. Is it safe? I've read here that it's wrong to use std::auto_ptr with STL containers. Does it apply to my situation here?
It is not safe, bacause when container will copy MyClass instnace default copy operator will call copy for all members - and for auto_ptr member too and we will have same situation as you describe in your question ( storing auto_ptr in container )
BTW: for avoid confusion at compile time add
private:
MyClass& operator=( const MyClass& );
MyClass( const MyClass& );
compiler output error if you will try use copy operators, this can save you from hours of debug.
As Neil Butterworth said, auto_ptr is probably not the way to go.
boost::shared_ptr clearly is, but you say you can't use boost.
Let me mention that you could download boost, extract what you need for shared\ptr only using the bcp tool and use boost::shared_ptr. It would only mean a few added hpp files in your project. I believe it's the right way to go.
It is not valid to have an object that contains an auto_ptr in a standard container. You run into undefined behavior. Two common problems:
std::vector<>::resize copies its argument into each created element. The first copy will "succeed" (see below why not), but each further copy will be empty, because the element copied is also empty!
If something during reallocation throws, you can happen to have some elements copied (to a new buffer) - but the copy being thrown away - and other elements not, because push_back must not have any effects if an exception is being thrown. Thus some of your elements are now empty.
As this is all about undefined behavior it does not really matter. But even if we try to come up with this behavior based on what we think is valid, we would fail anyway. All the member functions like push_back, resize and so on have a const reference that takes an object of type T. Thus, a reference of type T const& is tried to copied into elements of the vector. But the implicitly created copy constructor/copy assignment operator looks like T(T&) - that is, it requires a non-const object to be copied from! Good implementations of the Standard library check that, and fail to compile if necessary.
Until the next C++ version, you have to live with this. The next one will support element types that are merely movable. That is, a moved object does not need to be equal to the object moved to. That will allow putting streams, transfer-of-ownership pointers and threads into containers.
See what the Standard says for this (17.4.3.6):
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ Standard Library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause (20.1.5, 23.1, 24.1, 26.1).
I've posted a question as a follow-up
to this answer, see
Class containing auto_ptr stored in vector.
Assming your class does not have a user-defined copy constructor, then no, it is probably (see below) not safe. When your class is copied (as will happen when it is added to a vector) the copy constructor of the auto_ptr will be used. This has the weird behaviour of tranferring ownership of the thing being copied to the copy and, so the thing being copied's pointer is now null.
It is possible, though unlikely, that you actually want this behaviour, in which case an auto_ptr is safe. Assuming you do not, you should either:
add a copy constructor to manage the copying
Note this is not enough - see the follow-up question mentioned above for more info.
or:
use a smarter, possibly reference counted pointer, such as one of the boost smart pointers
Copying MyClass object will cause either call to assignment operator or copy constructor. If they are not overloaded to handle auto_ptr<> in unusual way, they will propagate the call to copy constructor (or assignment operator) to the auto_ptr<> member. This may lead to problems described in question you had linked.
The reason why it is not safe to instanciate a vector of auto_pointer is that there is an algorithm : sort(), that will do a copy of one object in your container on the stack. (sort() implements quicksort which needs a "pivot")
And therefore deleting it when going out of scpope of the sort() function.
As well any algorithm, or function of your own that are able to take your container as parameter, and copy one of its object on the stack will cause this issue as a result.
Well in your case, it is simple you must ensure your class does not behaves as an auto_ptr, or ensure you will never call such function/algorithm that can delete your underlying objects. The first solution is best, according to me :)
So your copy constructor and your affectation operator as well, should not give away property of the pointer object.
The best way to achieve that is to wrapp a boost smart pointer instead of an auto_ptr, to make your container safe when calling such function/algorithm.
By the way according to me, defining a better copy constructor/affectation operator to bypass this issue is not a good solution: I can't see a good copy constructor implementation (and affectation operator as well) that could keep safe the result of applying the sort() algorithm.
If you want to use a class that uses auto_ptr in a container, you can just provide a copy-constructor and assignment operator yourself:
class MyClass
{
private:
const std::auto_ptr<MyOtherClass> obj; // Note const here to keep the pointer from being modified.
public:
MyClass(const MyClass &other) : obj(new MyOtherClass(*other.obj)) {}
MyClass &operator=(const MyClass &other)
{
*obj = *other.obj;
return *this;
}
};
But as mentioned elsewhere, the standard lets containers make copies and assignments and assumes that the contained classes will behave in a specific manner that auto_ptr violates. By defining the methods above, you can make a class that contains an auto_ptr behave. Even if your implementation works fine with auto_ptrs, you run the risk of finding another implementation doesn't work. The standard only make guarantees of performance and observable behaviour, not implementation.
It will not work. auto_ptr doesn't count references which means at the first destructor call your pointer will be freed.
Use boost::shared_ptr instead.