【发布时间】:2022-02-17 00:17:16
【问题描述】:
我使用 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...
这引出了问题:
- 为什么
constrange 和const auto&lambda 参数的组合无法编译,而传递可变范围有效并按值获取 lambda 参数有效? - 我相信将非范围
std::find_if算法的 lambda 参数按值(auto而不是const auto&)会被认为是一种反模式,因为这会导致每个元素都被复制 -因此应该首选使用const auto&... 最小意外原则意味着我认为std::ranges的情况也是如此 - 不是这样吗?
【问题讨论】:
-
1) 请提供minimal reproducible example 2) can't reproduce、
stdext::flat_map似乎可以在 GCC 和 clang 中继上与std::ranges::find_if一起正常工作。 -
你也可以看看可能的实现here。也许将它复制到一个新文件上,这样您就可以四处看看问题是否是
flat_map缺少某些东西(别名成员、operator*等成员函数等)。 -
@Brian 请在此处找到示例:godbolt.org/z/r93f7qozr(我已经更新了问题以包含链接)...特别是我和你的区别在于地图是 const,而我将 lambda 参数作为 const ref
-
@SteveLorimer 太好了,很高兴我们缩小了范围!可能值得注意的是,non-const references and a mutable map 会出现同样的错误,而const references and a mutable map 会出现不。
-
注意,我会把它写成
auto it1 = std::ranges::find(map, 0, &decltype(map)::value_type::second);,但无论如何,这也行不通。你得到了很多没有满足的要求,比如 "no type named 'type' in 'struct std::common_reference<:pair int const>&&, std::pair&>'"
标签: c++ c++20 std-ranges