С ++ 11 передает пользовательскую функцию ha sh в unordered_map - PullRequest
2 голосов
/ 08 мая 2020

Я не уверен, что понимаю, почему это компилируется.

#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <queue>
using namespace std;



void thing() {
    auto hash = [](const std::pair<int, int> &pair) {
        return std::hash<string>()(to_string(pair.first));
    };
    auto map = std::unordered_map<std::pair<int, int>, int, decltype(hash)>();
}


int main() {

}

Я не передал функцию ha sh в конструктор - откуда он знает, что реализация ha sh a пара?

1 Ответ

3 голосов
/ 08 мая 2020

Он может компилироваться, потому что тип лямбда-выражения является анонимным классом, который может быть создан (но см. Примечание ниже). Блок кода - это метод этого класса operator()(). Этот класс создается как значение параметра по умолчанию конструктором std::unordered_map - с использованием типа лямбда-выражения, который является аргументом шаблона:

unordered_map( InputIt first, InputIt last,
               size_type bucket_count = /*implementation-defined*/,
               const Hash& hash = Hash(), /* <<<< INSTANTIATION HAPPENS HERE */
               const key_equal& equal = key_equal(),
               const Allocator& alloc = Allocator() );

Подробнее о природе лямбда-выражений см. В этом вопросе SO :

Что такое лямбда-выражение в C ++ 11?


Примечание. Как отмечают комментаторы, ваш код фактически не компилируется с C ++ 11 , поскольку неявный конструктор по умолчанию для анонимного класса, определенного лямбда-выражением, удален в C ++ 11. Это было изменено в C ++ 20: лямбда-выражения без захвата получают конструктор по умолчанию, поэтому теперь код компилируется.

...