Boost logo

Boost :

Subject: Re: [boost] Interest in StaticVector - fixed capacity vector
From: Dave Abrahams (dave_at_[hidden])
Date: 2011-10-19 13:26:44

on Wed Oct 19 2011, Nevin Liber <> wrote:

> On 16 October 2011 06:50, Dave Abrahams <dave_at_[hidden]> wrote:
>>> It's still silent, as it isn't the same interface even though the
>>> actual call looks the same.
>> Well, now we could pick nits over the meaning of "same interface."
> Are the "Requires" clauses in the Standard part of the interface or
> not?

Yes, absolutely. But that's just one function. I think I had in mind
the total interface of the class, frankly I've forgotten at this point.

I see a container that can never store more than N items, for some
reasonably small N, as fundamentally, semantically different from one
that is highly likely to be able to store any M items you have to deal
with, and for which you can't determine a hard limit N ahead of time
(no, max_size() doesn't count—that's typically just
numeric_limits<size_t>::max()). I grant you that we don't have a very
strict way of expressing this difference in a specification, but I think
that's just missing. I wouldn't, except in very special circumstances,
consider one of those containers to be a suitable replacement for the
other, despite the similarity of the specification text. Would you?

> I see the answer to that question as something fundamental, not
> picking nits.
> In my point of view they are part of the interface, as they describe
> when it is legal for me to make a particular function call.

Yes, but I think there's something else in the interface (abstractly)
that you may not be accounting for, and that clearly makes these two
push_backs different, even if you choose the throwing semantics.

>>> In some sense it is O(1), since N is bounded, but I know what you
>>> mean. :-)
>> There's also the nonthrowing part.
> I agree. Then again, the only alternative is not providing swap at all.

Sure. I'm not arguing there's something wrong with the throwing swap in
this case; I'm just saying the optimization of "no dynamic allocation,
ever" has consequences that ripple through the interface.

>> I'm not.  If you think I am, you've misconstrued me.  I'm just trying
>> to understand the design space and represent a point-of-view about
>> handling likely programmer errors that I think is important and
>> overlooked.
> When you mess with programmer's expectations, you get programmer
> errors.

A programmer who doesn't adjust his expectations when replacing
something essentially unbounded with something essentially bounded is in
for a rude surprise no matter what is done about this particular

Sounds like you just don't want to appreciate the point-of-view I'm
representing. That's OK, but I don't think I'll follow up on this post
in that case.

>> I do very much dislike the idea of having multiple interfaces for what
>> is essentially the same semantics.
> Of course, I'm arguing they are different interfaces, but to address
> this point, we have multiple interfaces for the same semantics all the
> time. c.push_back(x) is just c.insert(c.end(), x), c.clear() is just
> c.erase(c.begin(), c.end()), etc.

I believe you are misunderstanding. In fact, c.insert(c.end(),x) does
not (or did not, in C++03) give the same exception-safety guarantees as

> Just today I had to show someone the swap trick for releasing space in
> a vector because there is no obvious way to do it in C++03; I don't
> consider that a good thing.

Sorry, I don't see the relevance.

>> There are certainly applications where it's knowable statically that
>> the limit can never be violated where one might want to drop in a
>> bounded vector in place of std::vector, and having to spell push_back
>> some other way, as though it were essentially different, is ugly.
> I don't think we can resolve this. I see them as different
> interfaces; you may not. Subtle interface differences lead to subtle
> bugs.


Dave Abrahams
BoostPro Computing

Boost list run by bdawes at, gregod at, cpdaniel at, john at