Reputation: 7353
I am not sure I understand why this compiles.
#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() {
}
I haven't passed the hash function into the constructor -- how does it know the implementation to hash a pair?
Upvotes: 2
Views: 327
Reputation: 131626
It may compile because the lambda expression's type is an anonymous class - which can be instantiated (but see note below). The code block is that class' operator()()
method. This class is instantiated as a default parameter value by the constructor std::unordered_map
- using the lambda expression's type, which is a template argument:
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() );
For more on the nature of lambda expressions, see this SO question:
What is a lambda expression in C++11?
Note: As commenters note, your code doesn't actually compile with C++11, because the implicit default constructor for the anonymous class defined by a lambda expression is deleted in C++11. This has been changed in C++20: Non-capturing lambdas get a default constructor, so now the code does compile.
Upvotes: 3