Обратный вызов функции с ранее неизвестными аргументами в C и C ++ - PullRequest
1 голос
/ 03 февраля 2012

Я думал о выполнении функции take_timing, которая бы принимала время любой функции, переданной ей. любая функция означает, что аргументы, которые принимает этот обратный вызов, неизвестны вызывающей стороне. Это займет слишком аргументы для обратного вызова. Но так как он не знает, как его вызвать, потребуется другая функция обратного вызова, вызывающая функцию обратного вызова, написанная пользователем функции. Заглушка будет примерно такой:

void take_timing(
    void (*callback)(),
    void (*caller(void (*callback)(),void* args_struct),
    void* args_struct
)
{
    // Start timer

    caller(callback,args_struct);

    // Stop timer, read timings, record...
}

void some_caller(void (*callback)(),void* args_struct)
{
    // Cast "callback" to function signature
    // Cast args_struct to some struct with args
    // Call the callback with correct args signature
}

Итак, мои вопросы:

  1. Возможно ли это?
  2. Может ли он использовать список переменных аргументов, чтобы упростить его? Как? Я беспомощен в этом ...
  3. Есть ли лучший способ сделать это? Или просто лучше сделать take_timing для каждого конкретного случая?
  4. Есть ли для этого шаблон проектирования ООП для использования с C ++?

Я сам отказался от этого, но выразил это здесь из любопытства, может быть, очень полезных идей.

Ответы [ 3 ]

4 голосов
/ 03 февраля 2012

Просто возьмите функтор в качестве аргумента шаблона. Что-то вроде:

template<typename F>
nanoseconds take_timing(F f) {

    auto start = high_resolution_clock::now();
    f();
    auto end = high_resolution_clock::now();
    return end - start;
}

long long factorial(int i);

take_timing( [](){factorial(20);} ); // wrap call to function taking arguments in zero-argument lambda
3 голосов
/ 03 февраля 2012

Вам нужна поддержка varargs, которая существует в ANSI C. Если вы поищете ее, вы получите около миллиарда хитов Google. Вот один случайный случай: http://www.eskimo.com/~scs/cclass/int/sx11b.html

2 голосов
/ 03 февраля 2012

Один из способов справиться с этим - взять объект функции boost :: bind в качестве параметра: http://www.boost.org/doc/libs/1_48_0/libs/bind/bind.html

Вы можете скрыть тот факт, что замыкания связаны с макросами.

...