2014-10-14 3 views
0

Фон: у меня есть сценарий, в котором я должен допускать сравнение между двумя объектами-функторами, используя уникальный идентификатор для проверки, являются ли они равными (я не могу просто проверить, совпадают ли их адреса, как сами указатели функций t хранится в объекте). Изначально у меня была эта идея, чтобы просто запустить генератор ID при 0 и приращение бесконечности:Преобразование адреса функции в 64-разрядное целое: неопределенное/неуправляемое?

struct GenerateUniqueID{ 
    static std::size_t id_count = 0; 

    auto operator()() -> std::size_t { return (id_count++); } 
}; 

... Тем не менее, как я буквально тысячи и тысячи этих объектов, созданных через каждые несколько секунд, я на самом деле удалось для запуска в случае переполнения id_count до 0! Результаты были ... неприятными. Теперь вторая идея заключалась в том, что, поскольку эти функторы, очевидно, обертывают вокруг функции, я мог бы выполнить сравнение, преобразовывая адрес указателя функции в 64-разрядное целое и сохраняя это в классе для сравнения , См:

//psuedocode 
struct Functor{ 
    std::uint64_t id; 

    auto generate_id_from_function_address(function f) -> void { 
     id = reinterpret_cast<std::uint64_t>(&f); 
    } 
}; 

Теперь моя забота здесь проста: это литье функции указателей на 64-разрядных целых чисел плохо себя/неопределенным? На 32-битных архитектурах? На 64-битных архитектурах? На обоих? Моя главная проблема здесь в том, что с виртуальными функциями, поскольку я знаю, что для встроенных функций компилятор просто создает нестрочную версию, поэтому там нет проблемы.

+6

Вы думаете, что переполнены 64-битным счетчиком? При 4 миллиардах инкрементов в секунду это займет более века ... – Nemo

+0

'преобразование адреса указателя функции в 64-разрядное целое и сохранение этого в классе для сравнения' Почему бы не сохранить фактический указатель функции? –

+1

Nemo, я нацелен на совместимость с 32-разрядными ОС. @IgorTandetnik: Нет стандартного способа хранения одного указателя на функцию-член и/или статическую функцию. – Shokwav

ответ

2

Преобразование обычного указателя (не говоря уже о указателе функции) в uint64_t определяется реализацией, поскольку указатели могут быть шире 64 бит. Преобразование корректно определено, если вы используете uintptr_t (и этот тип существует).

Преобразование указателя функции в любой целочисленный тип определяется реализацией (даже если вы используете uintptr_t), поскольку указатели на функции могут быть более широкими, чем обычные указатели. Некоторые другие стандарты, такие как POSIX, явно разрешают это, поэтому в POSIX безопасно использовать указатели на указатели данных, такие как void* и до uintptr_t.

(Преобразование указателя на член в целое число, указатель данных, или регулярный указатель функции не определен, так и на практике, вероятно, чтобы всегда терпят неудачу, так как они больше, чем обычные указатели.)

Тем не менее, может быть проще просто использовать uint64_t вместо size_t для ваших уникальных идентификаторов. В принципе невозможно переполнять uint64_t, увеличивая его количество за счет их огромного диапазона.

+0

Так что мои подозрения верны. – Shokwav

 Смежные вопросы

  • Нет связанных вопросов^_^