https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120432

--- Comment #2 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> ---
(In reply to Patrick Palka from comment #1)
> Confirmed, that fix looks good to me.
> 
> FWIW our template operator[] is just the standard
> https://eel.is/c++draft/flat.map#access-4 with more generalized constraints:
> 
>   same_as<remove_cvref_t<_Key2>, _Key> || __transparent_comparator<_Compare>
> 
> The intent is to be able to dispatch the non-template overloads to this
> template and avoid having to introduce an actual helper function.

Yeah, but by giving the non-transparent-comparator flat_map's helper the same
name as the actual operator[] of the transparent-comparator flat_map, you end
up interfering with overload resolution on the non-transparent-comparator
flat_map's operator[].
(Disclosure: I once gave a whole conference talk on "When Should You Give Two
Things the Same Name?" My answer was, and remains, "Never gratuitously." :))

> >     static_assert(!C<std::flat_map<int, int>, volatile int>); // bogus error
> We can fix this by changing remove_cvref_t<K> to
> remove_const_t<remove_reference_t<K>> in the constraint, but I don't see why
> we'd want to reject this volatile index case?

One possible answer is "because the paper standard says so"; libc++ often
phrases this pseudo-helpfully as "we don't want to provide extensions because
then people will rely on them and get locked into our library, and lock-in is
bad." But I think a better answer in this case is "because using a volatile
index *will not actually compile*, so flat_map shouldn't gratuitously advertise
that signature to SFINAE."
https://godbolt.org/z/bdTK7nPKG

    std::flat_map<int, int> m;
    volatile int vi = 42;
    m[vi] = 1;

.../flat_map:1155:11: error: no matching member function for call to
'try_emplace'
 1155 |         { return try_emplace(std::forward<_Key2>(__x)).first->second; }
      |                  ^~~~~~~~~~~
<source>:15:6: note: in instantiation of function template specialization
'std::flat_map<int, int>::operator[]<volatile int &>' requested here
   15 |     m[vi] = 1;
      |      ^

Reply via email to