为什么在这种情况下我会在 C++ 中收到 C2064 和 c 2056 错误

问题描述

我正在用 C++ 做一个文件观察器,但经过一些重构后,我遇到了一些问题。主要是我明白是什么问题。我调用一个实际上不是函数函数,但我找不到这样的东西。所有的答案都说有一个名字被称为函数

这是我的标题

#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include <unordered_map>
#include <filesystem>

namespace fs = std::filesystem;

class FileWatcher
{
    size_t currentNumberOfFiles = 0;
    fs::path pathToWatch;
    std::unordered_map<fs::path,fs::file_time_type> pathsMap;
    std::string currentTime();
public:
    FileWatcher(fs::path path);
    void start();
};
    
#endif

和 .cpp 文件

#pragma warning(disable : 4996)
#include "FileWatcher.h"
#include "Event.h"

std::string FileWatcher::currentTime()
{
    auto Now = std::chrono::system_clock::Now();
    std::time_t NowTime = std::chrono::system_clock::to_time_t(Now);
    std::string currentSystemTime = std::ctime(&NowTime);
    return currentSystemTime;
}

FileWatcher::FileWatcher(fs::path pathToWatch)
{
    this->pathToWatch = pathToWatch;
    //create a map with last modification of a given file in the directory
    for (auto& file : fs::directory_iterator(this->pathToWatch))
    {
        pathsMap.emplace(file.path(),fs::last_write_time(file));
    }
}

void FileWatcher::start()
{
    while (true)
    {
        currentNumberOfFiles = std::distance(fs::directory_iterator(pathToWatch),fs::directory_iterator());

        for (std::unordered_map<fs::path,fs::file_time_type>::iterator it = pathsMap.begin(); it != pathsMap.end(); )
        {
            if (!fs::exists(it->first))
            {   
                if (currentNumberOfFiles < pathsMap.size())
                {
                    //std::cout << "File was erased" << std::endl;
                    it = pathsMap.erase(it);
                    //FileType fileType = ( ? FileType::FILE : FileType::DIRECTORY);
                    std::string time = this->currentTime();
                    Event event(EventType::DELETED,FileType::FILE,it->first,time);
                    event.printEvent();
                }
                else
                {
                    //std::cout << "Renamed" << std::endl;
                    it = pathsMap.erase(it);
                }
            }
            else
            {
                it++;
            }
        }
        
        for (auto& file : fs::directory_iterator(pathToWatch))
        {
            if (!pathsMap.count(file.path()))
            {
                //std::cout << "File has been created" << std::endl;
                pathsMap.emplace(file.path(),fs::last_write_time(file));
            }
            else
            {
                if (pathsMap.at(file.path()) != fs::last_write_time(file))
                {
                    //std::cout << "File has been modified" << std::endl;
                    pathsMap.at(file.path()) = fs::last_write_time(file);
                }
            }
        }
    }
}

这是错误列表:

Error list image

一个错误

Severity    Code    Description Project File    Line    Column  Category    Source  Suppression State
Error   C2056   illegal expression  ProgrammingAssignment   C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash 130 44      Build   

第二个错误

Severity    Code    Description Project File    Line    Column  Category    Source  Suppression State
Error   C2064   term does not evaluate to a function taking 1 arguments ProgrammingAssignment   C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash 131 53      Build   

这是在 filesystem 库中引用的地方错误列表。

template <class _Hasher,class _Kty>
_INLINE_VAR constexpr bool _Nothrow_hash = noexcept(
    static_cast<size_t>(_STD declval<const _Hasher&>()(_STD declval<const _Kty&>())));

这是错误输出

Build started...
1>------ Build started: Project: ProgrammingAssignment,Configuration: Debug Win32 ------
1>FileWatcher.cpp
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(131,53): error C2064: term does not evaluate to a function taking 1 arguments
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(155): message : see reference to variable template 'const bool _Nothrow_hash<std::hash<std::filesystem::path>,std::filesystem::path>' being compiled
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(155): message : while compiling class template member function 'size_t std::_Uhash_compare<_Kty,_Hasher,_Keyeq>::operator ()<_Kty>(const _Keyty &) noexcept(<expr>) const'
1>        with
1>        [
1>            _Kty=std::filesystem::path,1>            _Hasher=std::hash<std::filesystem::path>,1>            _Keyeq=std::equal_to<std::filesystem::path>,1>            _Keyty=std::filesystem::path
1>        ]
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(1218): message : see reference to variable template 'const bool _Nothrow_hash<std::_Umap_traits<std::filesystem::path,std::chrono::time_point<std::filesystem::_File_time_clock,std::chrono::duration<__int64,std::ratio<1,10000000> > >,std::_Uhash_compare<std::filesystem::path,std::hash<std::filesystem::path>,std::equal_to<std::filesystem::path> >,std::allocator<std::pair<std::filesystem::path const,10000000> > > > >,0>,std::filesystem::path>' being compiled
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(1218): message : while compiling class template member function 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::_Hash<std::_Umap_traits<_Kty,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>,std::_Uhash_compare<_Kty,_Keyeq>,_Alloc,false>>::erase<std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,0>(std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>) noexcept(<expr>)'
1>        with
1>        [
1>            _Ty=std::pair<const std::filesystem::path,std::filesystem::file_time_type>,1>            _Kty=std::filesystem::path,1>            _Alloc=std::allocator<std::pair<const std::filesystem::path,std::filesystem::file_time_type>>
1>        ]
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(130,44): error C2056: illegal expression
1>Done building project "ProgrammingAssignment.vcxproj" -- Failed.
========== Build: 0 succeeded,1 Failed,0 up-to-date,0 skipped ==========

解决方法

错误消息非常难以阅读,但基本上归结为缺少 std::hash<std::filesystem::path> 的实现。

std::unordered_map 使用散列对其元素进行排序。默认情况下,它在地图的 key_type 上使用 std::hash 的特化。但是,标准库没有为 std::hash 提供 std::filesystem::path 的特化,因此会出现错误。

因此,如果您想使用 std::filesystem::path 作为 key_typestd::unordered_map,您必须:

  • 提供您自己的 std::hash<std::filesystem::path> 专长,例如:
template <>
class std::hash<fs::path>
{
public:
    size_t operator()(const fs::path &path) const
    {
        return ... a hash of path ...;
    }
};

class FileWatcher
{
    ...
    std::unordered_map<fs::path,fs::file_time_type> pathsMap;
    ...
};
  • 使用 class 实现自定义 struct/operator(),该 std::filesystem::pathstd::unordered_map 作为输入并返回唯一值作为输出。然后您可以在 Hashstruct MyPathHash { size_t operator()(const fs::path &path) const { return ... a hash of path ...; } }; class FileWatcher { ... std::unordered_map<fs::path,fs::file_time_type,MyPathHash> pathsMap; ... }; 模板参数中明确声明该类型,例如:
std::map

否则,请改用 operator<。它使用 std::filesytem::path 对其元素进行排序,并且 ... #include <map> class FileWatcher { ... std::map<fs::path,fs::file_time_type> pathsMap; ... }; 实现了自己的 operator<,例如:

import pandas as pd
df = pd.DataFrame({'id1': ['A','A','C','S','S'],'id2': ['B','B','D','T','T'],'element': ['cat','dog','jaguar','kangaroo','elefant','lion','fox']})

df.groupby(['id1','id2'])['element'].unique()