我使用 SG14flat_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>;
如果我嘗試在std::ranges::find_if上使用flat_map,我會收到錯誤訊息:
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"; });
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果我使用 non-range 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 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
constrange 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_ifalgorithm's lambda arguments by value (autoas 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?
uj5u.com熱心網友回復:
為什么
const范圍和const auto&lambda 引數的組合無法編譯,而傳遞一個可變范圍有效并且按值獲取 lambda 引數有效?
首先,operator*()迭代器的flat_map定義如下:
reference operator*() const {
return reference{*kit_, *vit_};
}
而 的型別reference是pair,這意味著它operator*()會回傳一個prvalue,pair所以 lambda 的引數型別不能是auto&,也就是一個左值參考,因為它不能系結右值。
第二,const flat_map不建模input_range概念,即它的迭代器不建模input_iteratorwhich requires indirectly_readablewhich requires common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&>,前者是pair<const int&, const int&>&&,后者是pair<const int, int>&,兩者都沒有common_reference。
解決方法是只common_reference為它們定義,就像P2321一樣(這也意味著您的代碼在 C 23 中格式正確):
template<class T1, class T2, class U1, class U2,
template<class> class TQual, template<class> class UQual>
requires requires { typename pair<common_reference_t<TQual<T1>, UQual<U1>>,
common_reference_t<TQual<T2>, UQual<U2>>>; }
struct basic_common_reference<pair<T1, T2>, pair<U1, U2>, TQual, UQual> {
using type = pair<common_reference_t<TQual<T1>, UQual<U1>>,
common_reference_t<TQual<T2>, UQual<U2>>>;
};
詳情common_reference可以參考這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/425698.html
標籤:c c 20 std-ranges
上一篇:如何獲取轉換為字串的python串列,分配給C 結構中的屬性
下一篇:如何從另一個視圖設定過濾器?
