Refactored interval lookup operations#54
Conversation
… same as set::const_iterator
ldionne
left a comment
There was a problem hiding this comment.
From the PR description:
All stdlib implementations support this case
I don't think it's correct to claim that stdlibs support this since there is still disagreement on whether this is UB in the first place (which means ICL would merely be getting lucky with other implementations).
| @@ -39,7 +39,7 @@ jobs: | |||
| sources: "" | |||
There was a problem hiding this comment.
I didn't look at the patch in detail, but when I looked into fixing this myself, one of the things I needed to do was ensure that we also don't call .insert on the underlying std:: container with a key that is potentially overlapping with other elements already in the underlying container. IIRC what happens right now is that ICL will insert a potentially overlapping interval into the underlying container, and then merge it with surrounding intervals depending on the policy. But the initial insert call is UB because of SWO violation.
I don't think you're addressing that in this patch?
There was a problem hiding this comment.
Umm, good catch. Yes, I'm not addressing that, and if SWO violation in the way we're discussing is to be interpreted as UB then this patch is insufficient. Will try to come up with a regression test against libc++ v22.
There was a problem hiding this comment.
Added fixes for that in the PR. I wasn't able to write a regression test for the case: presumably because libc++ v22 hasn't translated its SWO assumptions in lookup operations over to insertion code?
| #if defined(ICL_USE_BOOST_MOVE_IMPLEMENTATION) ||\ | ||
| (BOOST_CXX_VERSION < 201402L && defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 220000) |
There was a problem hiding this comment.
This is silently ABI-breaking. I feel like it's probably more appropriate not to compile in this case.
There was a problem hiding this comment.
I don't think this is a problem in the context of Boost, which is abundantly not ABI-stable across C++ versions.
…eneral] with rewritten relational candidates
Closes #51. Includes regression tests from #53. Branched off https://github.com/boostorg/icl/tree/fix/interval_order.
Explanation of changes
Interval comparison is generally a partial order rather than a strict weak order (SWO). This does not pose any problem with associative containers as long as the intervals in the container are disjoint, since the induced order restricted to those is a SWO (indeed, a total order). A difficulty may arise when doing a lookup operation for an interval
kthat overlaps with E = elements(container), as the induced order over {k} ∪ E may not be a SWO. All stdlib implementations work in this case as implicitly expected by Boost.ICL except libc++ v22 or higher:Whether libc++'s behavior is conformant or not (and whether looking up a key that violates SWO is UB or not) is contested, see
but, regardless, we can solve the problem by resorting to heterogeneous lookup. When
kis of a type other thankey_typeand the compare predicate is transparent, lookup operations onkare defined by the standard in terms of elements being partitioned byk, without any reference to SWO compliance.boost::icl::detail::assoc_container_adaptor, in combination withboost::icl::detail::transparent_compare, forces lookup operations on the adapted container to be routed through itsheterogeneous lookup overloads, and does nothing for C++11 containers without het lookup. This circumvents libc++'s singular behavior except when in C++11 mode: in this case, we use Boost.Container, which supports het lookup even in C++11 (see
impl_config.hpp). Insert functions are also provided that prevent UB when the element would violate SWO (this is UB regardless of the resolution of libc++'s issue).Additional fixes
findfunctions are documented to return the first eligible element, which is not guaranteed bystd::(set|map)::find;assoc_container_adaptorfixes that.set::iteratoris the same type asset::const_iterator, which is not guaranteed generally and is certainly not the case forboost::container::set. Fixed byassoc_container_adaptor.ICL_USE_BOOST_MOVE_IMPLEMENTATION): this case wasn't being tested in CI.