Разница в реализации при использовании std :: find на std :: map между libc ++ и libstdc ++ - PullRequest
2 голосов
/ 25 октября 2019

Я пытаюсь подвести итог некоторым коллегам, как работает std::find, и я хотел показать им, как сложно использовать его на std::map (и почему они не должны), поэтому я начал возиться с компиляторомexplorer.

Я думаю, что я столкнулся с несоответствием реализации между 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.

Так что я озадачен, и мне интересно, какое из двух является желаемым поведением. Ссылки компилятора:

Ответы [ 2 ]

2 голосов
/ 25 октября 2019

Вы должны #include <algorithm>, как задокументировано здесь .

Вам просто (не) повезло, что одна библиотека неявно включила этот заголовок для вас, но вы действительно не должнызависит от этого.

0 голосов
/ 25 октября 2019

Если вы посмотрите на стандарт C ++, когда увидите, что единственный заголовок, который требуется для стандарта C ++ при включении заголовка <map>, - это заголовок <initializer_list>. То же самое относится и к заголовку <string>. Это единственный обязательный включенный заголовок: <initializer_list>.

. Реализациям разрешено включать любые другие заголовки в <map> и <string>. Однако это определяется реализацией.

Аналогичная ситуация имеет место, например, с заголовком <string>, когда используется заголовок <iostream>. Некоторые реализации включают заголовок <string> в заголовок <iostream>, другие не делают этого.

Таким образом, вы всегда должны включать все необходимые заголовки, если в стандарте явно не указано, что эти заголовки включены в другие используемые заголовки.

...