问题描述
我正在用 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);
}
}
}
}
}
这是错误列表:
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
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_type
的 std::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::path
将std::unordered_map
作为输入并返回唯一值作为输出。然后您可以在Hash
的struct 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()