I have a unordered map std::unordered_map<void (MyClass::*)(), double>
used to store the time that has elapsed since a function has been called. I'm getting an error saying that
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> >]'
What is causing this, and how do I fix it? Is there a better way to do what I trying to do?
std::unordered_map
stores its data using some calculations involving std::hash
function. As described in the documentation for std::hash
, under subsections "Standard specializations for basic types" and "Standard specializations for library types", there are only limited types that std::hash
can perform on and void (MyClass::*)()
is not one of them since its non-static and a non-static method pointer can not be used without an object.
One possible solution is to use std::string
as the key and when a function is called use the __func__
as the key inside the function.
This is a working solution:
#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();
}
Why do we need to use methodWrapper
? Why can't we just pass FuncPtr
as key type to the m_functionMap
? Because non-static method pointers can not be used without an object. That's the reason for this strange-looking line:
(myClass.*funcPtr)();
and the static method solution which I belive makes more sense:
#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();
}
In conclusion my suggestion is using __func__
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.