Skip to content

Commit 312c496

Browse files
committed
A. More conservative insert(auto&&) impl
1 parent 9be25df commit 312c496

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

stl/inc/flat_set

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)