[libcxx-commits] [libcxx] Reapply "[libc++] Avoid constructing additional objects when using map::at" (#160738) (PR #161485)

Nico Weber via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 3 07:21:09 PDT 2025


nico wrote:

Hm, ours looks different. Here's a reduced repro of ours:

```
% cat less.cc
#include <set>
#include <vector>

struct Paper {
  int a { 0 };
};

namespace std {
template <>
struct less<::Paper> {
  bool operator()(const ::Paper& lhs, const ::Paper& rhs) const {
    return lhs.a < rhs.a;
  }
};
}

template <class Key>
bool HasDuplicateItems(const std::vector<Key>& items) {
  std::set<Key> items_encountered;
  for (const Key& item : items) {
    bool inserted = items_encountered.insert(item).second;
    if (!inserted) {
      return true;
    }
  }
  return false;
}

bool f(std::vector<::Paper> p) {
  return HasDuplicateItems(p);
}
```

```
% cp out/gn/include/c++/v1/__config .
% cp out/gn/include/c++/v1/__assertion_handler .
```

```
% clang++ -c less.cc -std=c++20 -isystem libcxx/include -nostdinc++ -D_LIBCPP_HARDENING_MODE_DEFAULT=_LIBCPP_HARDENING_MODE_NONE -I.
In file included from less.cc:1:
In file included from libcxx/include/set:537:
In file included from libcxx/include/__tree:40:
libcxx/include/__utility/lazy_synth_three_way_comparator.h:43:54: error: no matching function for call to object of type 'const std::less<void>'
   43 |   _LIBCPP_HIDE_FROM_ABI bool __less() const { return __comp_(__lhs_, __rhs_); }
      |                                                      ^~~~~~~
libcxx/include/__tree:1759:20: note: in instantiation of member function 'std::__lazy_compare_result<std::less<void>, Paper, Paper>::__less' requested here
 1759 |     if (__comp_res.__less()) {
      |                    ^
libcxx/include/__tree:954:38: note: in instantiation of function template specialization 'std::__tree<Paper, std::less< ::Paper>, std::allocator<Paper>>::__find_equal<Paper>' requested here
  954 |           auto [__parent, __child] = __find_equal(__key);
      |                                      ^
libcxx/include/set:739:93: note: in instantiation of function template specialization 'std::__tree<Paper, std::less< ::Paper>, std::allocator<Paper>>::__emplace_unique<const Paper &>' requested here
  739 |   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __v) { return __tree_.__emplace_unique(__v); }
      |                                                                                             ^
less.cc:21:39: note: in instantiation of member function 'std::set<Paper>::insert' requested here
   21 |     bool inserted = items_encountered.insert(item).second;
      |                                       ^
less.cc:30:10: note: in instantiation of function template specialization 'HasDuplicateItems<Paper>' requested here
   30 |   return HasDuplicateItems(p);
      |          ^
libcxx/include/__functional/operations.h:374:60: note: candidate template ignored: substitution failure [with _T1 = const Paper &, _T2 = const Paper &]: invalid operands to binary expression ('const Paper' and 'const Paper')
  374 |   _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const
      |                                                            ^
  375 |       noexcept(noexcept(std::forward<_T1>(__t) < std::forward<_T2>(__u))) //
  376 |       -> decltype(std::forward<_T1>(__t) < std::forward<_T2>(__u)) {
      |                                          ~
In file included from less.cc:1:
In file included from libcxx/include/set:537:
In file included from libcxx/include/__tree:40:
libcxx/include/__utility/lazy_synth_three_way_comparator.h:44:57: error: no matching function for call to object of type 'const std::less<void>'
   44 |   _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __comp_(__rhs_, __lhs_); }
      |                                                         ^~~~~~~
libcxx/include/__tree:1765:27: note: in instantiation of member function 'std::__lazy_compare_result<std::less<void>, Paper, Paper>::__greater' requested here
 1765 |     } else if (__comp_res.__greater()) {
      |                           ^
libcxx/include/__tree:954:38: note: in instantiation of function template specialization 'std::__tree<Paper, std::less< ::Paper>, std::allocator<Paper>>::__find_equal<Paper>' requested here
  954 |           auto [__parent, __child] = __find_equal(__key);
      |                                      ^
libcxx/include/set:739:93: note: in instantiation of function template specialization 'std::__tree<Paper, std::less< ::Paper>, std::allocator<Paper>>::__emplace_unique<const Paper &>' requested here
  739 |   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __v) { return __tree_.__emplace_unique(__v); }
      |                                                                                             ^
less.cc:21:39: note: in instantiation of member function 'std::set<Paper>::insert' requested here
   21 |     bool inserted = items_encountered.insert(item).second;
      |                                       ^
less.cc:30:10: note: in instantiation of function template specialization 'HasDuplicateItems<Paper>' requested here
   30 |   return HasDuplicateItems(p);
      |          ^
libcxx/include/__functional/operations.h:374:60: note: candidate template ignored: substitution failure [with _T1 = const Paper &, _T2 = const Paper &]: invalid operands to binary expression ('const Paper' and 'const Paper')
  374 |   _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const
      |                                                            ^
  375 |       noexcept(noexcept(std::forward<_T1>(__t) < std::forward<_T2>(__u))) //
  376 |       -> decltype(std::forward<_T1>(__t) < std::forward<_T2>(__u)) {
      |                                          ~
2 errors generated.
```

Before this PR, the code built fine.

Is that `std::less` specialization invalid?

https://github.com/llvm/llvm-project/pull/161485


More information about the libcxx-commits mailing list