As stated in the std::future
constructor:
Default-constructed future objects are not valid
This just means calling the default constructor for the object, something like:
std::future<int> f;
This will call constructor #1 which states:
Default constructor. Constructs a std::future with no shared state.
After construction, valid() == false
.
As for the other part:
(unless move-assigned a valid future)
What is meant here is that the move constructor (future( future&& other )
#2) will be called which states:
Move constructor. Constructs a std::future with the shared state of
other using move semantics. After construction, other.valid() == false
.
Basically, the state of other
in this constructor is moved to this
. That means if other.valid() == true
then after the move constructor has returned other.valid()
will be false
and this.valid()
will be true
. If other.valid()
was false
to begin with then both will end up false
.
std::future<int> fut; // fut.valid() == false, default constructor
std::future<int> valid_fut = std::async(std::launch::async, [](){ return 42; }); // obtain a valid std::future..
// valid_fut.valid() == true here
//now move valid_fut into new_fut
std::future<int> new_fut(std::move(valid_fut));
// new_fut.valid() == true
// valid_fut.valid() == false
To summarize:
Calling the default constructor for an std::future
will result in valid() == false
. Always.
Calling the move constructor for an std::future
will result in valid() == true
only if other.valid()
was true
before moving from it. False otherwise.