使用指向成员函数的指针作为 unordered_map 中的键

发布于 2025-01-12 08:34:21 字数 537 浏览 0 评论 0 原文

我有一个无序映射 std::unordered_map 用于存储自调用函数以来所经过的时间。我收到一条错误消息,指出

error: use of returned function 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = void (MyClass::*)( ); _Tp = 双; _Hash = std::hash; _Pred = std::equal_to; _Alloc = std::allocator; >]'

是什么原因造成的,如何解决?有更好的方法来做我想做的事情吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

征棹 2025-01-19 08:34:21

std::unordered_map 使用一些方法存储其数据涉及 std::hash 函数。正如 std::hash 的文档中所述,在“基本类型的标准专业化”和“库类型的标准专业化”小节中,只有有限的类型 std::hash< /code> 可以执行,而 void (MyClass::*)() 不是其中之一,因为它是非静态的,并且在没有对象的情况下不能使用非静态方法指针。

一种可能的解决方案是使用 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?因为非静态方法指针不能在没有对象的情况下使用。这就是这条看起来奇怪的线的原因:

(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 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__.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文