使用指向成员函数的指针作为 unordered_map 中的键
Using a pointer to a member function as a key in unordered_map
我有一个无序映射 std::unordered_map<void (MyClass::*)(), double>
用于存储调用函数后经过的时间。我收到一条错误消息
error: use of deleted function ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = void (MyClass::*)(); _Tp = double; _Hash = std::hash<void (MyClass::*)()>; _Pred = std::equal_to<void (MyClass::*)()>; _Alloc = std::allocator<std::pair<void (MyClass::* const)(), double> >]’
这是什么原因造成的,我该如何解决?有没有更好的方法来做我想做的事情?
std::unordered_map
stores its data using some calculations involving std::hash
函数。正如 std::hash
的文档中所述,在“基本类型的标准特化”和“库类型的标准特化”小节下,std::hash
和 void (MyClass::*)()
只能执行有限的类型不是其中之一,因为它的 non-static 和 non-static 方法指针不能在没有对象的情况下使用。
一个可能的解决方案是使用 std::string
作为键,当函数被调用时使用 __func__
作为函数内部的键。
这是一个可行的解决方案:
#include <unordered_map>
#include <iostream>
#include <chrono>
#include <thread>
class MyClass
{
public:
using FuncPtr = void (MyClass::*) ();
using WrapperPtr = void (*) (MyClass&, void (MyClass::*) ());
void func1() {
}
void insert(std::pair<WrapperPtr, unsigned long long> pair) {
m_functionMap.insert(pair);
}
void printTime() {
std::hash<WrapperPtr> hashKey;
std::hash<unsigned long long> hashValue;
for (auto itr{ begin(m_functionMap) }; itr != end(m_functionMap); ++itr) {
std::cout << hashKey(itr->first) << " " << itr->second << std::endl;
}
}
private:
std::unordered_multimap<WrapperPtr, unsigned long long> m_functionMap;
};
void methodWrapper(MyClass& myClass, MyClass::FuncPtr funcPtr) {
myClass.insert({ &methodWrapper, std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() });
(myClass.*funcPtr)(); // Actual call.
}
int main()
{
MyClass myObj;
methodWrapper(myObj, &MyClass::func1);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
methodWrapper(myObj, &MyClass::func1);
myObj.printTime();
}
为什么我们需要使用methodWrapper
?为什么我们不能将 FuncPtr
作为键类型传递给 m_functionMap
?因为 non-static 没有对象就不能使用方法指针。这就是 strange-looking 行的原因:
(myClass.*funcPtr)();
我认为静态方法解决方案更有意义:
#include <unordered_map>
#include <iostream>
#include <chrono>
#include <thread>
class MyClass
{
public:
static void func1() {
m_functionMap.insert({ &MyClass::func1, std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() });
}
static void printTime() {
std::hash<decltype(&MyClass::func1)> hashKey;
std::hash<unsigned long long> hashValue;
for (auto itr{ begin(m_functionMap) }; itr != end(m_functionMap); ++itr) {
std::cout << hashKey(itr->first) << " " << itr->second << std::endl;
}
}
private:
static std::unordered_multimap<decltype(&MyClass::func1), unsigned long long> m_functionMap;
};
std::unordered_multimap<decltype(&MyClass::func1), unsigned long long> MyClass::m_functionMap{};
int main()
{
MyClass::func1();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
MyClass::func1();
MyClass::printTime();
}
总而言之,我的建议是使用 __func__
。
我有一个无序映射 std::unordered_map<void (MyClass::*)(), double>
用于存储调用函数后经过的时间。我收到一条错误消息
error: use of deleted function ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = void (MyClass::*)(); _Tp = double; _Hash = std::hash<void (MyClass::*)()>; _Pred = std::equal_to<void (MyClass::*)()>; _Alloc = std::allocator<std::pair<void (MyClass::* const)(), double> >]’
这是什么原因造成的,我该如何解决?有没有更好的方法来做我想做的事情?
std::unordered_map
stores its data using some calculations involving std::hash
函数。正如 std::hash
的文档中所述,在“基本类型的标准特化”和“库类型的标准特化”小节下,std::hash
和 void (MyClass::*)()
只能执行有限的类型不是其中之一,因为它的 non-static 和 non-static 方法指针不能在没有对象的情况下使用。
一个可能的解决方案是使用 std::string
作为键,当函数被调用时使用 __func__
作为函数内部的键。
这是一个可行的解决方案:
#include <unordered_map>
#include <iostream>
#include <chrono>
#include <thread>
class MyClass
{
public:
using FuncPtr = void (MyClass::*) ();
using WrapperPtr = void (*) (MyClass&, void (MyClass::*) ());
void func1() {
}
void insert(std::pair<WrapperPtr, unsigned long long> pair) {
m_functionMap.insert(pair);
}
void printTime() {
std::hash<WrapperPtr> hashKey;
std::hash<unsigned long long> hashValue;
for (auto itr{ begin(m_functionMap) }; itr != end(m_functionMap); ++itr) {
std::cout << hashKey(itr->first) << " " << itr->second << std::endl;
}
}
private:
std::unordered_multimap<WrapperPtr, unsigned long long> m_functionMap;
};
void methodWrapper(MyClass& myClass, MyClass::FuncPtr funcPtr) {
myClass.insert({ &methodWrapper, std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() });
(myClass.*funcPtr)(); // Actual call.
}
int main()
{
MyClass myObj;
methodWrapper(myObj, &MyClass::func1);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
methodWrapper(myObj, &MyClass::func1);
myObj.printTime();
}
为什么我们需要使用methodWrapper
?为什么我们不能将 FuncPtr
作为键类型传递给 m_functionMap
?因为 non-static 没有对象就不能使用方法指针。这就是 strange-looking 行的原因:
(myClass.*funcPtr)();
我认为静态方法解决方案更有意义:
#include <unordered_map>
#include <iostream>
#include <chrono>
#include <thread>
class MyClass
{
public:
static void func1() {
m_functionMap.insert({ &MyClass::func1, std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() });
}
static void printTime() {
std::hash<decltype(&MyClass::func1)> hashKey;
std::hash<unsigned long long> hashValue;
for (auto itr{ begin(m_functionMap) }; itr != end(m_functionMap); ++itr) {
std::cout << hashKey(itr->first) << " " << itr->second << std::endl;
}
}
private:
static std::unordered_multimap<decltype(&MyClass::func1), unsigned long long> m_functionMap;
};
std::unordered_multimap<decltype(&MyClass::func1), unsigned long long> MyClass::m_functionMap{};
int main()
{
MyClass::func1();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
MyClass::func1();
MyClass::printTime();
}
总而言之,我的建议是使用 __func__
。