Как добавить элементы в std::unordered_map с нестандартным типом ключа?

Пишу:

std::filesystem::path logs_dir;
std::unordered_map<std::filesystem::file_time_type, std::filesystem::path> paths;
for (auto& iter : std::filesystem::directory_iterator(logs_dir))
        paths.insert(iter.last_write_time(), iter.path());

Ответ убил:

Error C2664: cannot convert argument 1 from 'std::filesystem::file_time_type' to 'std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>'

Полный текст ошибки:

Error   C2664   'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::_Hash<std::_Umap_traits<_Kty,std::filesystem::path,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::insert(std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,std::_Node_handle<std::_List_node<std::pair<const std::filesystem::file_time_type,std::filesystem::path>,std::_Default_allocator_traits<_Alloc>::void_pointer>,_Alloc,std::_Node_handle_map_base,_Kty,std::filesystem::path> &&)': cannot convert argument 1 from 'std::filesystem::file_time_type' to 'std::_List_const_iterator<std::_List_val<std::_List_simple_types<_Ty>>>'

Исходя из возвращаемых методами типов, всё ок должно было быть. А в тексте ошибки как-то неочевидно, откуда берётся этот _List_iterator. Пытался с std::pair, std::make_pair сделать — не работает.

К слову, если не добавлять элементы в unordered_map, а только объявить его, то будет такая ошибка компиляции:

Error   C2280   'std::_Uhash_compare<_Kty,_Hasher,_Keyeq>::_Uhash_compare(const std::_Uhash_compare<_Kty,_Hasher,_Keyeq> &)': attempting to reference a deleted function

Что ещё больше путает. Это какая-то несовместимость стандартных типов STL?


Ответы (2 шт):

Автор решения: AlrondPrime

Можно хранить в качестве ключа не std::filesystem::file_time_type, а std::chrono::system_clock::rep, он же long long

std::filesystem::path logs_dir;
std::unordered_map<std::chrono::system_clock::rep, std::filesystem::path> paths;
for (auto &iter : std::filesystem::directory_iterator(logs_dir))
    paths.insert({ iter.last_write_time().time_since_epoch().count(),iter.path() });

Смысл вроде как тот же, хотя и в ином формате

→ Ссылка
Автор решения: Maxim

В метод insert нужно передавать std::pair<const Key, T>

paths.insert(std::make_pair(key, value));

или

paths.insert({key, value});

https://en.cppreference.com/w/cpp/container/unordered_map/insert

У типа std::filesystem::file_time_type нет функции для вычисления хеша, которая необходима для std::unordered_map, но вы можете сами написать её и передать в качестве параметра шаблона

#include <iostream>
#include <filesystem>
#include <unordered_map>
#include <chrono>
#include <functional>

struct FileTimeHash
{
    std::size_t operator()(std::filesystem::file_time_type const& time) const {
        return std::hash<unsigned long long>{}(std::chrono::duration_cast<std::chrono::nanoseconds>(time.time_since_epoch()).count());
    }
};

int main() {
    std::filesystem::path logs_dir(".");
    std::unordered_map<std::filesystem::file_time_type, std::filesystem::path, FileTimeHash> paths;
    for (auto& iter : std::filesystem::directory_iterator(logs_dir))
        paths.insert({iter.last_write_time(), iter.path()});
    return 0;
}

https://en.cppreference.com/w/cpp/container/unordered_map

Либо можно использовать std::map

#include <iostream>
#include <filesystem>
#include <map>

int main() {
    std::filesystem::path logs_dir(".");
    std::map<std::filesystem::file_time_type, std::filesystem::path> paths;
    for (auto& iter : std::filesystem::directory_iterator(logs_dir))
        paths.insert({iter.last_write_time(), iter.path()});
    return 0;
}

https://en.cppreference.com/w/cpp/container/map

→ Ссылка