C ++转换函数指针,以独特的“哈希”键(C++ Converting function point

2019-07-31 00:42发布

在底部硒原来的问题。

我想我明白你们在说什么了 - 因为成员函数指针的内部结构是编译器/机器具体实在是无法做到这一点,我想。 因此,即使它的工作原理,当我测试它 - 我不能保证它会在其他的编译器/机器。

有另一种方式去了解我想要什么呢?

我有一个模板类和该类的基本模板类,和我有一个包含所有委托类应该调用,调用时发生的事件的一个std ::地图委托类。

其原因我需要一个地图是,既要确保相同的成员函数(事件指向成员函数)不ADDE多于一次,以使其能够从地图使用最初用于当对象和成员函数删除事件实例化的事件对象。

template <class T_arg1> struct EventBase1
{
public:
    bool operator < (const EventBase1 &event1) const { return _key < event1._key; };
    virtual void operator()(T_arg1 t1) const {};
    std::pair<intptr_t, intptr_t> _key;
};

template <class T, class T_arg1> struct Event1: public EventBase1<T_arg1>
{
    template <class T_arg1> friend class Delegate1;
    typedef typename void (T::*Method)(T_arg1);
private:
    Method _method;
    T* _object;
public:
    Event1(T* object, Method method): _object(object), _method(method)
    {
        _key = std::pair<intptr_t, intptr_t>(reinterpret_cast<intptr_t>(object), reinterpret_cast<intptr_t>( reinterpret_cast<void*&>(method)));
    };
    virtual void operator()(T_arg1 t1) const {
        (_object->*_method)(t1);
    };
};

template <class T_arg1> class Delegate1
{
public:
    typedef typename EventBase1<T_arg1> T_event;
    void operator += (T_event* observer)
    {
        assert(observer);
        _observers[*observer] = observer;
    };
    void operator -= (const T_event &observer)
    {
        std::map<T_event, T_event*>::iterator i = _observers.find(observer);
        if(i != _observers.end()) {
            delete i->second;
            _observers.erase(i);
        }
    };
    void operator()(T_arg1 t1)
    {
        for(std::map<T_event, T_event*>::iterator i = _observers.begin(); i != _observers.end(); i++) {
            (*(i->second))(t1);
        }
    };
private:
    std::map<T_event, T_event*> _observers;     
};

原来的问题:

我存储函数指针在一个std::map ,和我生成我的针对地图键如下: std::pair<int, int>( (int)((int*)object), (int)(static_cast<const void*>(&method)) )

method是一种功能(方法)的指针,以及object是一个指向该方法的对象。

它的工作原理,但我有一个鬼鬼祟祟的怀疑,我拿到钥匙的第二部分的方式是不完全正确的。

我从来没有完全理解函数指针,但我想,我越来越指针的地址,而不是函数的地址,编译器不会让我做这样的((int)(static_cast<const void*>(method)))

所以我的问题是 - 如何获取从函数指针,将相同的,如果我后来得到了得到另一个函数指针指向同一个方法的关键唯一的钥匙吗?

在此先感谢,马丁

Answer 1:

第二个是不合法的:正式,你不能一个指针转换成一个函数的指针数据(和void*是一个指向数据)。 此外,你不能保证能够为任何指针转换为int ; 如果转换是唯一合法int至少作为指针(这意味着你的代码编译失败在大多数64位系统)一样大。

这种情况有解决的几种方法。 首先,在大多数(所有?)现代机器,poitners到函数指针和数据确实具有相同的大小和代表性。 (POSIX需要它,事实上,即使它不是在我使用的第一个Unix机器的情况下)。如果我们假定这一点,您可以通过使用保证了足够大的整数类型intptr_t使用,并且“绝招”编译器间接的额外层次:

std::pair<intptr_t, intptr_t>(
    reinterpret_cast<intptr_t>( reinterpret_cast<void*&>( object ) ),
    reinterpret_cast<intptr_t>( reinterpret_cast<void*&>( method ) ) )

(这个假设是objectmethod是你的指针指向对象和功能。)

请注意,这并不为指向成员函数工作。 成员指针功能是完全不同的东西,我不认为有这种方式来使用他们作为重点任何有效的方式(因为它们可能,而且经常做,含有填充物,或取消领域,在某些情况下) 。

对于这个问题,正式挂牌,这是不是真的保证即使是正常的指针。 该标准允许指针有无关位,或几个不同的指针表示为比较相等。 然而在实践中,这是大多数(全部?)现代机器安全。



Answer 2:

你应该罚款写作:

reinterpret_cast<uintptr_t>(method)

[编辑] -为指针的方法,你将不得不留在C风格的类型转换,如本SO解释: reinterpret_cast的到void *不能与函数指针工作

和方法为你suspec指针的指针,所以它不是你想要的

uintptr_t的是过INT更好,因为它被保证是大小为指针相同



文章来源: C++ Converting function pointer to unique “hash” key