我正在使用 SG14 flat_map
作为容器。
与标准映射一样,它需要 Key
和 Value
模板参数。
然而,与标准映射不同的是,它不会在二叉搜索树中存储 std::pair<Key, Value>
,而是将键和值存储在两个单独的容器中(额外的模板参数默认为 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
然后按以下方式定义了一些类型:
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>;
如果我尝试在
flat_map
上使用std::ranges::find_if
,就会出现错误: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"; });
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果我使用非范围的
find_if
,一切都“正常工作”。auto it = std::find_if(map.begin(), map.end(), [](auto& kv) { return kv.second.name == "foo"; });
为什么
std::ranges::find_if
无法工作?godbolt上的示例:https://godbolt.org/z/r93f7qozr 编辑: @Brian提供了一个成功编译的示例,尽管与我的略有不同,特别是我的映射是
const
,并且我将lambda参数作为const ref
接受...这引出了以下问题:
const
范围和const auto&
lambda 参数的组合为什么无法编译,而传递可变范围可以工作,并且按值接受 lambda 参数也可以工作?- 我相信将非范围的
std::find_if
算法的 lambda 参数按值(auto
而不是const auto&
)作为一种反模式,因为这会导致每个元素被复制 - 因此使用const auto&
应该是首选... 最小惊讶原则意味着我认为在std::ranges
中也应该是这样的 - 这不是这种情况吗?
stdext::flat_map
似乎可以与std::ranges::find_if
很好地配合使用。flat_map
缺少某些东西(别名成员、成员函数如operator*
等)。 - Enlicoauto it1 = std::ranges::find(map, 0, &decltype(map)::value_type::second);
,但是无论如何,它都不起作用。你会得到很多未满足的要求,比如“在'struct std::common_reference<std::pair<const int&, const int&>&&, std::pair<const int, int>&>'中没有名为'type'的类型”。 - JHBonarius