如何解决在 C 中使用默认参数包装 C++ 函数
namespace foo {
void bar(int a,int b = 1);
}
我想在 C 代码中使用这个函数。一个明显的解决方案是定义两个这样的函数:
void foo_bar_1(int a)
{ foo::bar(a,1); }
void foo_bar_2(int a,int b)
{ foo::bar(a,b); }
这些可以很容易地包含在 C 代码中。但是,对于多个默认参数,这会变得很丑陋,拥有单个包装函数会更好。我想过做这样的事情:
#define _test_foo_numargs(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define test_foo(...) do { \
if (_test_foo_numargs(__VA_ARGS__) == 1) \
test_foo_1(__VA_ARGS__); \
else if (_test_foo_numargs(__VA_ARGS__) == 2) \
test_foo_2(__VA_ARGS__); \
} while (0)
但这不起作用,因为对 test_foo_1
和 test_foo_2
的调用都必须有效才能编译。
有没有更好的方法来做到这一点?
解决方法
我会在这里提供我自己的解决方案,以防没有人有更好的解决方案,并且将来有人遇到同样的问题:
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
int _test_foo_1(int a)
{ return a; }
int _test_foo_2(int a,int b)
{ return a + b; }
int _test_foo_va(size_t num_args,...)
{
va_list args;
va_start(args,num_args);
switch (num_args) {
case 1:
return _test_foo_1(va_arg(args,int));
case 2:
return _test_foo_2(va_arg(args,int),va_arg(args,int));
}
va_end(args);
}
#define _test_foo_numargs(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define test_foo(...) _test_foo_va(_test_foo_numargs(__VA_ARGS__),__VA_ARGS__)
int main()
{
printf("%d\n",test_foo(1));
printf("%d\n",test_foo(1,2));
}
这当然很不安全,因为如果传递的参数太少或太多,它都会编译。
,您可以执行以下操作:
#define TAKE_9(_1,_2,_3,_4,_5,_6,_7,_8,_9,...) _9
#define COUNT(...) TAKE_9(__VA_ARGS__,8,7,6,5,4,3,2,1)
#define CONCAT_(A,B) A ## B
#define CONCAT(A,B) CONCAT_(A,B)
#define SELECT(NAME,...) CONCAT(NAME,COUNT(__VA_ARGS__))(__VA_ARGS__)
#define foo_bar(...) SELECT(foo_bar_,__VA_ARGS__)
COUNT
可以升级为处理 0
参数,如果您的编译器支持它
#define COUNT(...) TAKE_9(__VA_ARGS__ __VA_OPT__(,) 8,1,0)
为了避免不得不写 foo_bar_N
,你可以这样做:
// ...
#define FUNC_WITH_DEFAULT_ARG_2(func,DEFAULT,...) TAKE_3(__VA_ARGS__ __VA_OPT__(,) \
func(__VA_ARGS__),\
func(__VA_ARGS__,TAKE_2 DEFAULT),\
func(TAKE_1 DEFAULT,TAKE_2 DEFAULT) )
#define FUNC_WITH_DEFAULT_ARG_3(func,...) TAKE_4(__VA_ARGS__ __VA_OPT__(,TAKE_2 DEFAULT,TAKE_3 DEFAULT),TAKE_3 DEFAULT) )
// Choose on or other,error message for misuse might differ
// RequiredParameter is just a name for "better" error message when not enough parameter are given
#define foo_bar(...) FUNC_WITH_DEFAULT_ARG_2(foo_bar_impl,(RequiredParameter,1),__VA_ARGS__)
#define foo_bar2(_1,...) FUNC_WITH_DEFAULT_ARG_3(foo_bar_impl,(_1,0),__VA_ARGS__)
void foo_bar_impl(int a,int b)
{ foo::bar(a,b); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。