tags:

views:

103

answers:

2

Consider the following:

std::vector<int> vec(1); // vector has one element
std::fill(vec.begin(), vec.begin(), 42);
std::fill(vec.begin()+1, vec.end(), 43);
std::fill(vec.end(), vec.end(), 44);

Will all of the std::fill usages above result in defined behavior? Am I guaranteed that vec will remain unmodified? I'm inclined to think "yes", but I want to make sure the standard allows such usage.

+1  A: 

Although I don't believe it's specifically forbidden in the standard, I would say no. The standard requires that iterator ranges be of type [first, last) which includes first and everything up to but not including last. Passing in the same value for first and last doesn't make logical sense with this definition as it would be both included and not included, so I would expect to get undefined behavior back.

EDIT: Cleaned up my initial response, and adding this: after brushing up on my mathematical interval notation, I've discovered that an interval of the form [x,x) is defined as the empty set. So my above answer is wrong -- I would NOT expect to get undefined behavior.

JonM
Which is it? "I would say yes" or "I would expect to get undefined behavior"?
John Kugelman
I guess wasn't quite clear which question I was answering -- the 'yes' was in response to both the title question and the first question you asked in the text: "Will all of the std::fill usages above result in defined behavior?".
JonM
Oh wow. I misread the question multiple times, even when copy + pasting that. The answer should be "no". Sorry. *facepalm*
JonM
Still can't parse this response really. The range [x,x) is well defined as an empty range (24.1/7). It also translates naturally into the loop `(auto iter = x; iter != x; ++iter)`.
MSalters
[first,last) isn't really read as "includes first and everything up to but not including last." It's reads more like "first <= *x* < last", or "anything greater than or equal to first and less than last". You see then, that if first == last, then no value of *x* satisfies the equation, so it is an empty set. By the same token, [ *x*,*x* ) = ( *x*,*x* ] = ( *x*,*x* ) = ∅
P Daddy
+1 for link and the clarifications on [x,x) and empty set that resulted from your answer. :-)
Emile Cormier
+7  A: 

No, if doesn't cause undefined behavior.

The standard defines empty iterator range in 24.1/7 and nowhere it says that supplying an empty range to std::fill algorithm causes undefined behavior.

This is actually what one would expect from a well-thought through implementation. With algorithms that handle emtpy range naturally, imposing the requirement to check for empty range on the caller would be a serious design error.

AndreyT
+1 Thanks for citing standard.
Emile Cormier
@AndreyT Isn't there an undefined behavior in his second example? I can see that `begin() == end()` when the range is empty, but `begin()+1` is not `end()`, right?
AraK
@Arak: In my second example, `begin()+1==end()` because `vec.size()==1` (note use of constructor taking size).
Emile Cormier
@Emile Sorry, lool it was me who missed that, sorry AndreyT :)
AraK
@AraK: No. Note that the vector is created with size 1 from the very beginning. So, `begin() + 1` is `end()`.
AndreyT