在libc++和libstdc++之间的std::map上使用std::find时的实现差异



我正试图向一些同事总结std::find是如何工作的,我想向他们展示在std::map上使用它有多棘手(以及为什么他们不应该这样做(,所以我开始摆弄编译器资源管理器。

我想我遇到了libc++libstdc++之间的实现差异,因为下面的代码段是在以前的上编译的

#include <string>
#include <map>
int main (){
std::map<std::string, int> myMap;
myMap["string1"] = 100;
std::map<std::string, int>::value_type element("string1", 100);
auto it = std::find(myMap.begin(), myMap.end(), element);
}

但未能编译,后者生成以下错误

error: no matching function for call to 'find'
auto it = std::find(myMap.begin(), myMap.end(), element);
^~~~~~~~~
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/streambuf_iterator.h:373:5: note: candidate template ignored: could not match 'istreambuf_iterator' against '_Rb_tree_iterator'
find(istreambuf_iterator<_CharT> __first,
^
1 error generated.

所以我很困惑,我想知道这两者中的哪一个是理想的行为。编译器资源管理器链接:

  • 使用libc++https://godbolt.org/z/KDsMsC
  • 使用libstdc++https://godbolt.org/z/g3DqlJ

您必须#include <algorithm>,如本文所述。

你只是运气不好,有一个库为你隐式地包含了这个头,但你真的不应该依赖它

如果您仔细查看C++标准,当使用标头<map>时,C++标准要求包含的唯一标头是标头<initializer_list>。这同样适用于标头<string>。这是唯一需要的包含标头是<initializer_list>

允许实现在<map><string>中包括任何其他报头。然而,它是由实现定义的。

例如,当使用报头<iostream>时,报头<string>也发生类似的情况。一些实现方式在报头CCD_ 15中包括报头<string>

因此,如果Standard没有明确指定这些标头包含在其他已使用的标头中,则应始终包含所有必需的标头。

最新更新