Чтобы вызвать функцию с переменным числом с неименованными аргументами другой функции с переменным числом - PullRequest
9 голосов
/ 21 марта 2011

У меня есть две переменные функции как foo(format, ...) и bar(format, ...).Я хочу реализовать функцию foo, чтобы она могла вызывать bar с тем же списком аргументов, что и у нее.То есть

foo(format...)
{
 ...
 bar(format, ...);
}

Например, вызов foo("(ii)", 1, 2) вызовет bar с теми же аргументами bar("(ii)", 1, 2).Как реализовать эту функцию foo?

PS: функция bar из устаревшей библиотеки, я не могу изменить ее интерфейс.

Ответы [ 4 ]

11 голосов
/ 22 марта 2011

Не может быть сделано, пока все, что у вас есть, это куча, если функции с ... аргументами.

Вы должны заранее планировать подобные вещи и реализовывать каждую вариационную функцию в два этапа

void vfoo(format, va_list *args) {
  /* Process `*args` */
}

void foo(format, ...) {
  va_list args;
  va_start(args, format);
  vfoo(format, &args);
  va_end(args);
}

После того как каждая из ваших переменных функций реализована с помощью пары функций va_list * и ..., вы можете делегировать вызовы, используя va_list * версии функций

.
void vfoo(format, va_list *args) {
  ...
  vbar(format, args);
  ...
}
8 голосов
/ 22 марта 2011

GCC может создавать вызовы функций во время выполнения .

foo() {
   void *args = __builtin_apply_args();
   void *ret = __builtin_apply(bar, args, ???);
    __builtin_return(ret);
}

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

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

3 голосов
/ 22 марта 2011

Краткий ответ - вы не можете.Сделать брусок va_list.Если вы хотите привязать это к одному конкретному компилятору, вы можете сделать это с помощью встроенной сборки, но со стандартным C или C ++ это невозможно.

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

2 голосов
/ 22 марта 2011

Это работает в C ++:

#include <iostream>

template<typename Format>
void meheer(const Format& format) {
  std::cout << format << std::endl;;
}

template<typename Format, typename Elt, typename ... Args>
void meheer(const Format& format, const Elt & e, const Args&... args) {
  std::cout << format << e;
  meheer(format, args...);
}

template<typename Format, typename ... Args>
void ohai(const Format& format, const Args&... args) {
  meheer(format, args...);
}

int main(int argc, char ** argv) {
  ohai(1,2,3);

  return EXIT_SUCCESS;
}

Выход:

12131

Конечно, это специфично для C ++ 0x, но это работает в моей не совсем новой версии gcc. Смотрите также: http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic_templates

Обновление Добавлен пример полной длины.

...