Как хранить различные типы указателей на функции вместе? - PullRequest
2 голосов
/ 10 июля 2011

Обычные указатели могут быть сохранены с использованием универсального void*.например,

void* arr[10];
arr[0] = pChar;
arr[1] = pINt;
arr[2] = pA;

Некоторое время назад я натолкнулся на дискуссию о том, что void* может быть недостаточно способным хранить указатель на функцию без потери данных на всех платформах (скажем, 64-битных и более).Хотя я не уверен в этом факте.

Если это так, то каков наиболее переносимый способ хранения коллекции указателей на функции?[Примечание: Этот вопрос не дает удовлетворительного ответа на этот вопрос.]

Редактировать : я буду хранить указатели на эту функцию с индексом.При каждом обращении к этой коллекции происходит привязка типов.На данный момент мне интересно только сделать массив или vector из него.]

Ответы [ 4 ]

9 голосов
/ 10 июля 2011

Вы можете преобразовать указатель функции в другой указатель на функцию любого типа и обратно без потерь.

Таким образом, если вы выполняете вызов с помощью указателя функции, вы вначале вводите его обратно в правильный тип, вы можете хранить все свои указатели функций в виде:

typedef void (*fcn_ptr)(void);  // 'generic' function pointer

fcn_ptr arr[10];
6 голосов
/ 10 июля 2011

Указатель на функцию может быть преобразован в указатель на функцию другого типа с помощью reinterpret_cast. Если вы преобразуете его обратно в исходный тип, вы гарантированно получите исходное значение, чтобы затем использовать его для вызова функции. (ИСО / МЭК 14882: 2003 5.2.10 [expr.reinterpret.cast] / 6)

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

1007 * Е.Г. *

int main()
{
    int a( int, double );
    void b( const char * );

    void (*array[])() = { reinterpret_cast<void(*)()>(a)
                        , reinterpret_cast<void(*)()>(b) };

    int test = reinterpret_cast< int(*)( int, double) >( array[0] )( 5, 0.5 );
    reinterpret_cast< void(*)( const char* ) >( array[1] )( "Hello, world!" );
}

Естественно, вы потеряли много безопасности типов и у вас будет неопределенное поведение , если вы вызовете функцию через указатель на функцию другого типа.

3 голосов
/ 10 июля 2011

Используйте объединение типов указателей на функции, это работает как на C, так и на C ++ и обеспечивает достаточную память для указателей (которые, вероятно, имеют одинаковый размер, но ...)

2 голосов
/ 10 июля 2011

Есть несколько вещей, которые составляют тип указателя на функцию.

Если эти функции не одинаковы для всех указателей на функциитогда вы не сможете разумно хранить их в одном и том же контейнере.

Однако вы можете связать различные аспекты в std::function, который является вызываемым объектом, который требует только подписи аргумента и возврататип должен быть единообразным.

Возможно, пришло время переосмыслить проблему с точки зрения виртуальных функций.Имеет ли эта путаница указателей на функции целостный интерфейс, который вы можете выразить?Если нет, то вы все равно обречены: -)

RE: Hasturkun, вы можете хранить гетерогенные указатели функций в объединениях, да, это просто POD, но вам также нужно будет хранить информацию о том, какого типауказатель это так, что вы можете выбрать правильный член для вызова.С этим связаны две проблемы:

  • есть накладные расходы на элемент,
  • , вам нужно вручную проверять, что вы постоянно используете правильный вариант, это бремяс нелокальными эффектами - это распространяющийся яд.

Намного лучше иметь один контейнер для каждого типа, это прояснит код и сделает его более безопасным.Или используйте прокси, например std::function, чтобы все они имели одинаковый тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...