我有两个可变函数foo(format, ...)
和bar(format, ...)
。我想实现函数foo
,以便它可以使用相同的参数列表调用bar
。也就是说,
foo(format...)
{
...
bar(format, ...);
}
例如,调用foo("(ii)", 1, 2)
将使用相同的参数bar
调用bar("(ii)", 1, 2)
。该foo
函数应如何实现?
PS:函数bar
来自遗留库,我无法更改其界面。
答案 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
更新添加了完整的示例。