[英]C++ & varargs with different compilers
我试图将用GCC编写的C ++项目重新编译为clang,它给我带来了varargs方法的一些问题。
注意 :该项目也应该使用不符合c ++-11的编译器进行编译,因此在这里我不能使用花哨的C ++ 11语法。
GCC不加警告地接受以下代码(1):
void Set(TreeIter &it, ...) {
va_list va;
va_start(va, it);
gtk_list_store_set_valist(*this, const_cast<TreeIter *>(&it), va);
va_end(va);
}
和(2):
void AddTail(...) {
TreeIter it;
gtk_list_store_append(*this, &it);
va_list va;
va_start(va, this);
gtk_list_store_set_valist(*this, &it, va);
va_end(va);
}
当CLANG发出警告时:
(1):
./ootree.h:444:30: warning: 'va_start' has undefined behavior with reference types [-Wvarargs]
(2):
./ootree.h:476:30: warning: second parameter of 'va_start' not last named argument [-Wvarargs]
我可以轻松地通过用副本替换TreeIter引用来修复(1)(标准似乎要求我这样做),但是我找不到简单的解决方法(2),下面是一个最小的独立示例,其中显示了行为,并且该程序不仅适用于gcc,而且适用于clang,但那些警告非常令人恐惧...
#include <stdio.h>
#include <stdarg.h>
struct T {
void print(...) {
va_list va;
va_start(va, this);
vprintf("%d %d %d\n", va);
va_end(va);
}
};
int main() {
T().print(2, 4, 6);
}
(2)的解决方案是显式地采用前2个参数,可能会提供1个参数的重载:
void AddTail(gint column, GValue *value, ...) {
TreeIter it;
gtk_list_store_append(*this, &it);
gtk_list_store_set_value(*this, &it, column, value);
va_list va;
va_start(va, value);
gtk_list_store_set_valist(*this, &it, va);
va_end(va);
}
void AddTail(gint column) {
TreeIter it;
gtk_list_store_append(*this, &it);
assert(column == -1);
}
您可以将(2)更改为
static void AddTail(T* that, ...) {
TreeIter it;
gtk_list_store_append(*that, &it);
va_list va;
va_start(va, that);
gtk_list_store_set_valist(*that, &it, va);
va_end(va);
}
并更改来自T().print(2, 4, 6);
的调用T().print(2, 4, 6);
到T::print(T(), 2, 4, 6);
。
甚至在第一个参数处添加一个虚拟标签:
struct variadic_tag {};
void AddTail(variadic_tag, ...) {
TreeIter it;
gtk_list_store_append(*that, &it);
va_list va;
va_start(va, that);
gtk_list_store_set_valist(*that, &it, va);
va_end(va);
}
并更改T().print(2, 4, 6);
到T().print(variadic_tag{}, 2, 4, 6);
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.