On Saturday, 16 July 2016 14:40:09 UTC+3, Alain Ketterlin wrote:
> Öö Tiib <
oot...@hot.ee> writes:
>
> > On Friday, 15 July 2016 03:51:54 UTC+3, Lynn McGuire wrote:
> >> "stl - C++: How can I stop map's operator[] from inserting bogus
> >> values? - Stack Overflow"
> >>
http://stackoverflow.com/questions/10684888/c-how-can-i-stop-maps-operator-from-inserting-bogus-values
> >>
> >> Looks like the fix is to use find () instead of [].
> >>
> >> Am I missing anything here ?
> >
> > The 'std::map' template is IMHO actually *overburdened* with
> > element-searching operations. There are 'std::map::operator[]',
> > 'std::map::find', 'std::map::lower_bound' and 'std::map::at'.
>
> operator[] is here to save one search through the map for logic like:
> "if it's there, update it, otherwise insert it", because insert() will
> not overwite an existing entry. I agree the choice of operator[] for
> this semantic is unfortunate (and it works only with default
> constructible types). I guess syntax like "m[k] = v;" to populate a map
> was irresistible, as was the whole operator overloading craze at that
> time.
Your analysis seems correct. Operator overloading was fancy feature
and all container example codes do start by filling containers with
bogus values (that is unusual use-case in actual code).
Also the novices deserve some of "Gotcha!" and "RTFM!" anyway.
Sad that C++ has somewhat too lot of that on each step.
>
> lower_bound is a different beast: it uses the strict ordering of keys to
> locate a position, but you can't use it to know whether the key is
> present without an additional comparison.
I imagine that 'lower_bound' is not different beast but component.
Other three operations feel like convenience wrappers around 'lower_bound'
that do that last additional compare internally:
// what 'm[k]' does
auto it = m.lower_bound(k);
if (it == m.end() || m.key_comp()(k, it->first)) // <- the last compare
{
// 'at' throws here; 'find' assigns 'm.end()' to 'it'
it = m.emplace_hint(it, k, Value());
}
// now 'it->second' is same as 'm[k]'
>
> > So real question is perhaps when to use one or other from these 4.
> > My impression is that best is to use 'at' when lack of searched
> > element is exceptional (or "impossible").
> > If lack of searched element is normal then we should choose one of
> > other three depending on what we do when element wasn't found.
> > When we never insert the missing element then best is 'find'.
> > When we always insert the missing element then best is 'operator[]'.
> >
> > When something about other 3 operations did not suit us (for example
> > that we only sometimes insert that missing element) then 'lower_bound'
> > (and 'emplace_hint') is likely the tool.
>
> Yes, different use cases. Probably not minimal in terms of operations
> (compare with Java Map, for instance), but coherent as a whole.
Some things are clearly impossible to do with Java Map without
needlessly searching it twice. The use case of map::operator[] is most
unusual for me but the problem domains likely differ.