@@ -472,16 +472,24 @@ private:
472472 const iterator _End = end();
473473 const iterator _Where = lower_bound(_Val);
474474 if (_Where != _End && _Keys_equal(*_Where, _Val)) {
475+ // NOTE: if contains(val), the _STL_ASSERT(find(key(val))!=end (==_Where)) cannot be done without
476+ // potential side effect.
475477 return pair{_Where, false};
476478 }
477479 if constexpr (is_same_v<remove_cvref_t<_Ty>, _Kty>) {
478480 return pair{_Cont.emplace(_Where, _STD forward<_Ty>(_Val)), true};
479481 } else {
480482 // for flat_set::insert(auto&&)
481483 _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent && is_constructible_v<_Kty, _Ty>);
484+ // NOTE: !contains(val).
482485 _Kty _Keyval(_STD forward<_Ty>(_Val));
483- _STL_ASSERT(_Check_where(_Where, _Keyval), "The input type was not equivalent to key_type!");
484- return pair{_Cont.emplace(_Where, _STD move(_Keyval)), true};
486+ _STL_ASSERT(!contains(_Keyval), "find(val)==end but find(key(val))!=end");
487+ // NOTE: Not trusting the strict equivalence(so that lower_bound(val)==lower_bound(key(val))) of val and
488+ // key(val), so reuse _Emplace_hint instead, with the hope that, if really strictly equivalent, then the
489+ // _Emplace_hint will not pose extra lower_bound cost; if not, the key(val) will be inserted at the
490+ // correct position.
491+ return pair{_Emplace_hint(_Where, _STD move(_Keyval)),
492+ true /*guaranteed by the precondition and checked by the assertion*/};
485493 }
486494 }
487495 }
@@ -536,10 +544,18 @@ private:
536544 return _Cont.emplace(_Where, _STD forward<_Ty>(_Val));
537545 } else {
538546 // for flat_set::insert(hint,auto&&)
547+ // NOTE: In the above code, the hint is used as the hint for seeking lower_bound. If val
548+ // is strictly equivalent to key(val), then this also works as if treating as insertion position, so the
549+ // _Emplace_hint will also not make extra lower_bound search.
550+ //
551+ // I cannot imagine how hint can be used or provided in a meaningful way if not strictly equivalent. At
552+ // least one full lower_bound search is required either in deciding the ?contains(val) or
553+ // lower_bound(key(val)), so the time complexity constraint cannot hold true. Anyway, using
554+ // _Emplace_hint can at least guarantee that the key(val) will be inserted at the correct position.
539555 _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent && is_constructible_v<_Kty, _Ty>);
540556 _Kty _Keyval(_STD forward<_Ty>(_Val));
541- _STL_ASSERT(_Check_where(_Where, _Keyval), "The input type was not equivalent to key_type! ");
542- return _Cont.emplace (_Where, _STD move(_Keyval));
557+ _STL_ASSERT(!contains( _Keyval), "find(val)==end but find(key(val))!=end ");
558+ return _Emplace_hint (_Where, _STD move(_Keyval));
543559 }
544560 }
545561 }
0 commit comments