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

Reply via email to