Все объекты C++, включая указатели на функции-члены, представлены в памяти как массив символов. Таким образом, вы можете попробовать:
bool (Class::*fn_ptr)() = &Class::whatever;
const char *ptrptr = static_cast<const char*>(static_cast<const void*>(&fn_ptr));
Теперь лечить ptrptr
, как указывает на массив (sizeof(bool (Class::*)()))
байт, а хэш или сравнить эти байты. Вы можете использовать unsigned char
вместо char
, если хотите.
Это не гарантирует ложных срабатываний - в C++ 03 указателями на функции-члены являются POD, что означает, среди прочего, что они могут быть скопированы с использованием memcpy. Это означает, что если они имеют одинаковые байтовые байтовые значения, то они одинаковы.
Проблема состоит в том, что представление хранилища указателей функций-членов может включать в себя биты, которые не участвуют в значении, поэтому они не обязательно будут одинаковыми для разных указателей на одну и ту же функцию-член. Или компилятор может по какой-то неясной причине иметь более одного способа указывать на одну и ту же функцию одного и того же класса, которые побайтно не равны. В любом случае вы можете получить ложные негативы. Вам нужно будет посмотреть, как на самом деле работают указатели на функции. Он должен реализовать operator==
для указателей функций-членов, и если вы узнаете, как тогда вы, вероятно, можете определить порядок и хэш-функцию.
Это потенциально сложно: указатели на функции неловко, и хранилище, вероятно, будет включать в себя разные количества неучастия «незаполненного пространства» в зависимости от того, на какую функцию указывает (виртуальная, унаследованная). Поэтому вам, вероятно, придется довольно сильно взаимодействовать с деталями реализации компилятора. Эта статья может помочь вам при запуске: http://www.codeproject.com/KB/cpp/FastDelegate.aspx
Более простой альтернативой может быть линейный поиск по массиву, чтобы «канонизировать» все ваши указатели на функции, а затем сравнивать и хешировать на основе положения «канонического», экземпляр этого указателя функции в вашем массиве. Зависит от ваших требований к производительности. И даже если есть требования, имеет ли класс (и его производные классы) так много функций, что линейный поиск займет так много времени?
typedef bool (Class::*func)();
vector<func> canon;
size_t getIndexOf(func fn_ptr) {
vector<func>::iterator it = find(canon.begin(), canon.end(), fn_ptr);
if (it != canon.end()) return it - canon.begin();
canon.push_back(func);
return canon.size() - 1;
}
Обычно нет указаний на хэш-указатель, поскольку он указывает прямо на предмет, к которому вы хотите получить доступ.Укажите код, который иллюстрирует то, о чем вы просите. – 2009-08-25 13:24:48
Когда вы скажете, что один указатель функции «меньше», чем другой? –
@bojan: Если единственная цель сравнения состоит в том, чтобы хранить их в отсортированном списке, любое детерминированное упорядочение будет делать. Например, двоичное значение. – erikkallen