使用另一个可变参数函数的未命名参数调用可变参数函数

时间:2011-03-21 20:58:54

标签: c++ c variadic-functions

我有两个可变函数foo(format, ...)bar(format, ...)。我想实现函数foo,以便它可以使用相同的参数列表调用bar。也就是说,

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

例如,调用foo("(ii)", 1, 2)将使用相同的参数bar调用bar("(ii)", 1, 2)。该foo函数应如何实现?

PS:函数bar来自遗留库,我无法更改其界面。

4 个答案:

答案 0 :(得分:11)

如果函数带有...个参数,只要你拥有的只是一堆,就无法完成。

你必须提前计划这样的事情,并以两阶段的方式实现每个可变的功能

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);
  ...
}

答案 1 :(得分:8)

海湾合作委员会可以construct function calls at runtime

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

???是参数占用的堆栈空间量,计算时不一定是微不足道的:您需要了解参数是什么以及有关它们如何传递的特定于体系结构的详细信息。

其他GCC扩展允许进一步使用宏和内联函数。

答案 2 :(得分:3)

简短回答 - 你不能。使吧成为va_list。如果您愿意将其锁定到一个特定的编译器,您可以使用内联汇编来实现,但使用标准C或C ++则无法实现。

作为一般规则,您应该始终使用va_list实现vararg函数,然后使用包装省略号函数调用真正的va_list函数。

答案 3 :(得分:2)

这适用于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

更新添加了完整的示例。