Все объекты 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;
}
person
Steve Jessop
schedule
25.08.2009