std :: map, std :: unordered_map - сужающее преобразование в списке инициализаторов - PullRequest
7 голосов
/ 21 января 2020

Это ошибка или стандарт разрешает это?

#include <iostream>
#include <map>
#include <unordered_map>

int main() {
    std::unordered_map<int,int> mm {{44,44}, {33.3, 54}, {222.2,222.2}};
    for(auto& [f,s] :mm) {
        std::cout<<f<<" - "<<s<<std::endl;
    }

    std::map<int,int> m {{44,44}, {33.3, 54}, {222.2,222.2}};
    for(auto& [f,s] :m) {
       std::cout<<f<<" - "<<s<<std::endl;
    }
}

Проверьте это на wandbox.org с помощью clang10 и gcc10. С std::set и std::unordered_set.

такой проблемы нет.

1 Ответ

8 голосов
/ 21 января 2020

Тип элемента std::map и std::unordered_map равен std::pair. Проблема в том, что std::pair имеет шаблонный конструктор,

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y );

Инициализирует first с std::forward<U1>(x) и second с std::forward<U2>(y).

Например, если {33.3, 54}, U1 выводится как double, а U2 выводится как int, обратите внимание, что это точное совпадение, и для использования этого конструктора при построении std::pair не требуется никаких преобразований. , то и сужения не происходит.

С другой стороны, для std::set, с учетом std::set<int> s {33.3};, будет использован конструктор std::set, принимающий std::initializer_list<int>, и std::initializer_list<int> будет инициализирован с {33.3} происходит узкое преобразование.

...