I'm using the SG14 flat_map
as a container.
As per a standard map, it takes Key
and Value
template parameters.
Unlike a standard map, however, it doesn't store std::pair<Key, Value>
in a binary search tree, but rather stores the keys and values in two separate containers (additional template arguments which default to std::vector
)
template<
class Key,
class Mapped,
class Compare = std::less<Key>,
class KeyContainer = std::vector<Key>,
class MappedContainer = std::vector<Mapped>
>
class flat_map
It then defines a number of types as follows:
using key_type = Key;
using mapped_type = Mapped;
using value_type = std::pair<const Key, Mapped>;
using key_compare = Compare;
using const_key_reference = typename KeyContainer::const_reference;
using mapped_reference = typename MappedContainer::reference;
using const_mapped_reference = typename MappedContainer::const_reference;
using reference = std::pair<const_key_reference, mapped_reference>;
using const_reference = std::pair<const_key_reference, const_mapped_reference>;
If I attempt to use std::ranges::find_if
on the flat_map
, I get an error:
error: no type named ‘type’ in
‘struct std::common_reference<std::pair<const Key&, const Value&>&&,
std::pair<const Key, Value>&>’
121 | auto it = std::ranges::find_if(map, [](auto& kv) { return kv.second.name == "foo"; });
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If I use a non-range find_if
, everything "just works"
auto it = std::find_if(map.begin(), map.end(), [](auto& kv) { return kv.second.name == "foo"; });
Why does the std::ranges::find_if
not work?
Example on godbolt: https://godbolt.org/z/r93f7qozr
Edit:
@Brian provided an exemplar which successfully compiles - albeit with slight differences to mine - notably my map is const
, and I take the lambda argument as a const ref
...
This begs the questions:
- Why does the combination of
const
range andconst auto&
lambda argument fail to compile, while pasing a mutable range works and taking the lambda argument by value works? - I believe it would be considered somewhat of an anti-pattern to take the non-range
std::find_if
algorithm's lambda arguments by value (auto
as opposed toconst auto&
) as this will cause every element to be copied - and therefore usingconst auto&
should be preferred... principle of least surprose means I assumed the same would be the case withstd::ranges
- is this not the case?