| Issue |
178847
|
| Summary |
Enforcing heterogeneous lookup in associative containers can break code relying on specializations of `std::less`
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
var-const
|
Consider a deliberately extreme example ([Godbolt](https://godbolt.org/z/b5sT768xq)):
```cpp
struct Foo {
int v = 0;
};
bool operator<(const Foo&, const Foo&) = delete;
namespace std {
template <>
struct less<Foo> {
bool operator()(const Foo& a, const Foo& b) const { return a.v < b.v; }
};
}
std::set<Foo> s;
s.insert(Foo{1});
```
`Foo` has no `operator<` and relies on a specialization of `std::less` for key comparisons in standard associative containers. I haven't done comprehensive research, but from a glance, the Standard doesn't seem to disallow user-provided specializations of `std::less`, and `[associative.reqmts]` seems to consistently express requirements through the comparator type, without requiring `operator<` to be defined. So at least initially, this doesn't seem to be undefined behavior (happy to be proven otherwise).
Before https://github.com/llvm/llvm-project/pull/157866, libc++ would use `std::less<Foo>` as the comparator and compile this code fine. After the patch essentially enables heterogeneous lookup by default, the user-provided specialization of `std::less` is ignored in favor of `std::less<void>`, which relies on `operator<` being defined for the type. In corner cases like the above, this is observable and can result in a compilation failure.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs