The std::move()
in the code below issues a runtime warning when compiled in Visual Studio 2013 (with Debug configuration) because it detects that dest
is a nullptr
. However, the source range is empty, so dest
should never be accessed.
The C++ standard may be unclear as to whether this should be allowed?
It states: Requires: result shall not be in the range [first,last).
A nullptr
would seem to satisfy that requirement.
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec;
int* dest = nullptr;
// The range [begin(vec),end(vec)) is empty, so dest should never be accessed.
// However, it results in an assertion warning in VS2013.
std::move(std::begin(vec), std::end(vec), dest);
}
The debug build of STL in Visual Studio does additional parameter validation. In this case, it is validating that dest is not null since it shouldn't be, which is failing. The release build may very well act as you expect, never using dest but that doesn't make the input data valid.
The debug build of STL is trying to help you by saying, "your input is bad". While the bad input might not be a problem in some circumstances, the validator can't know under what conditions you are passing it bad data. Personally, I would much rather have VS tell me about bad input in debug builds than have a runtime exception thrown in production.
Sure, you might do something like this:
But the validator doesn't know that so it assumes the worst, especially since fixing it is very easy for you (just always pass in a valid output iterator) and not warning you about it could have terrible consequences on your application at runtime in production.
Not only does the Requires: clause need to be satisfied, but everything in the Effects: and Returns: clause needs to be satisfied as well. Let's go through them:
As
first == last
, then the range[result, result + 0)
must be a valid range.[iterator.requirements.general]/p7 states:
And p6 of the same section states:
From these paragraphs I conclude that given:
Then
[dest, dest)
forms a valid empty range. So the first sentence in the Effects: paragraph looks ok to me:There are no non-negative integers
n < 0
, and so no assignments can be performed. So the second sentence does not prohibitdest == nullptr
.[expr.add]/p8 specifically allows one to add 0 to any pointer value and the result compares equal to the original pointer value. Therefore
dest + 0
is a valid expression equal tonullptr
. No problems with the Returns: clause.I see no reasonable way to interpret that
dest
would be "in" an empty range.This confirms that no assignments can be done.
I can find no statement in the standard that makes this example anything but well-formed.
This answer is derived from the comment by @Philipp Lenk. If he supplies an answer and you find it acceptable, choose his over mine and please up-vote his original comment.
The above code is not valid. You cannot assign to
*dest
in this case, therefore per the standard you cannot pass a nullptr in for the dest.