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

            Bug ID: 125374
           Summary: std::flat_map unconditionally moves from lvalue keys
                    in _M_try_emplace
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: andre.balandin at gmail dot com
  Target Milestone: ---

The implementation of std::flat_map in libstdc++ incorrectly moves from lvalue
keys when using a transparent comparator (e.g., std::less<>). 

According to C++23 specification, when inserting via operator[] or try_emplace
with a transparent comparator, the key container should construct the element
using perfect forwarding (std::forward<K>(k)). If an lvalue is passed, it must
be copied, leaving the original object intact.

However, in 'libstdc++-v3/include/std/flat_map', inside the helper method
`_M_try_emplace`, the key is unconditionally moved:

__key_it = _M_cont.keys.insert(__key_it, std::move(__k));

Since `__k` is a forwarding reference (`_Key2&&`), using `std::move` forces a
move constructor even when `_Key2` resolves to an lvalue reference
(std::string&), resulting in the silent destruction/emptying of the source
object.

Tested minimal reproducible code (main.cpp):

#include <iostream>
#include <flat_map>
#include <string>

int main() {
    std::flat_map<std::string, int, std::less<>> m;
    std::string s = "test";
    m[s] = 1;
    std::cout << (s.empty() ? "BUG" : "OK") << "\n";
}

Actual runtime output:
BUG

Expected runtime output:
OK

Reply via email to