Bug 105717 - [10/11/12/13 Regression] cannot create unordered_map from range of types convertible to value_type
Summary: [10/11/12/13 Regression] cannot create unordered_map from range of types conv...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 13.0
: P3 normal
Target Milestone: 13.0
Assignee: François Dumont
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2022-05-24 10:29 UTC by Jonathan Wakely
Modified: 2022-06-15 18:30 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.4, 4.8.0
Known to fail: 12.1.0, 13.0, 4.8.1
Last reconfirmed: 2022-05-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2022-05-24 10:29:36 UTC
+++ This bug was initially created as a clone of Bug #56112 +++

François observed that I fixed construction for PR 56112, but we still don't support insertion of such types:

#include <unordered_map>
#include <utility>
#include <assert.h>

struct Key
{
  explicit Key(const int* p) : value(p) { }
  ~Key() { value = nullptr; }

  bool operator==(const Key& k) const
  { return *value == *k.value; }

  const int* value;
};

struct hash
{
  std::size_t operator()(const Key& k) const noexcept
  { return *k.value; }
};

struct S
{
  static int _count;

  int value;
  operator std::pair<const Key, int>() const
  {
    ++_count;
    return { Key(&value), value };
  }
};

int S::_count = 0;

int main()
{
    S s[1] = { {2} };
    std::unordered_map<Key, int, hash> m(s, s + 1);
    assert( S::_count == 1 );

    std::unordered_multimap<Key, int, hash> mm(s, s + 1);
    assert( S::_count == 2 );

    m.insert(s, s + 1);
    assert( S::_count == 3 );

    mm.insert(s, s + 1);
    assert( S::_count == 4 );
}


This worked in 4.7
Comment 1 François Dumont 2022-06-15 18:30:26 UTC
    libstdc++: [_Hashtable] Insert range of types convertible to value_type PR 105717
    
    Fix insertion of range of instances convertible to value_type.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/105717
            * include/bits/hashtable_policy.h (_ConvertToValueType): New.
            * include/bits/hashtable.h (_Hashtable<>::_M_insert_unique_aux): New.
            (_Hashtable<>::_M_insert(_Arg&&, const _NodeGenerator&, true_type)): Use latters.
            (_Hashtable<>::_M_insert(_Arg&&, const _NodeGenerator&, false_type)): Likewise.
            (_Hashtable(_InputIterator, _InputIterator, size_type, const _Hash&, const _Equal&,
            const allocator_type&, true_type)): Use this.insert range.
            (_Hashtable(_InputIterator, _InputIterator, size_type, const _Hash&, const _Equal&,
            const allocator_type&, false_type)): Use _M_insert.
            * testsuite/23_containers/unordered_map/cons/56112.cc: Check how many times conversion
            is done.
            * testsuite/23_containers/unordered_map/insert/105717.cc: New test.
            * testsuite/23_containers/unordered_set/insert/105717.cc: New test.