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