Я хочу хранить пустые указатели на функции вместе с их типом - PullRequest
1 голос
/ 23 сентября 2011

Я пытаюсь сделать так, чтобы вектор содержал пустые указатели на функции, которые впоследствии будут вызываться последовательно.
Итак, допустим, у меня есть три функции.int a(), void b();, bool c();

Мой вектор vector<void *> vec;

И моя функция, которая хранит указатели на функции.

void registerFunction(void *func)
{
    vec.push_back(func);
}

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

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

Примечание : функции не всегда будут иметь тип, например, void (*)(), Я также хочу добавить методы, т.е.void (someclass::)().Это требует слишком много?Должно ли это работать?

Ответы [ 3 ]

4 голосов
/ 23 сентября 2011

Нельзя преобразовать указатель функции в void*.Это недопустимо.

Если все функции можно вызывать с нулевыми аргументами и вам не нужен тип возвращаемого значения, вы можете использовать std::vector<std::function<void()>> (function также можно найти в Boost и TR1если ваша стандартная библиотека C ++ не поддерживает ее).

Хотя, если я правильно помню, преобразование возвращаемого типа не допускается в реализации C ++ 11 std::function, и в этом случае вам может понадобиться что-то вродеследующее:

template <typename T>
struct ignore_result_impl
{
    ignore_result_impl(T fp) : fp_(fp) { }
    void operator()() { fp_(); }
    T fp_;
};

template <typename T>
ignore_result_impl<T> ignore_result(T fp)
{
    return ignore_result_impl<T>(fp);
}

int g() { return 42; }
std::function<void()> f(ignore_result(g));

(В реализации Boost я знаю, что вы можете использовать function<void()> напрямую, но я уверен, что это больше не разрешено в C ++ 11. Я могу ошибаться, и яБуду признателен за разъяснения в комментариях, если кто-то знает.)

0 голосов
/ 23 сентября 2011

void* не может безопасно использоваться в качестве общего типа указатель на функцию (хотя вы могли бы избежать этого).

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

Что касается хранения типа, я не уверен, что этовозможный.Если количество возможностей ограничено, вы можете использовать тип перечисления и оператор switch.

Но вам, вероятно, будет лучше использовать дизайн, основанный на наследовании.

0 голосов
/ 23 сентября 2011

Пока все функции следуют одной и той же сигнатуре типа, вы можете привести указатели void к этому типу.

Лучшим решением является определение типа функции:

typedef int(*fun_ptr)();
vector<fun_ptr> vec;

Тогда вам не понадобится приведение.

...