首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不同编译器的C++ & varargs

不同编译器的C++ & varargs
EN

Stack Overflow用户
提问于 2015-12-03 15:28:57
回答 2查看 447关注 0票数 2

我正在尝试重新编译一个用GCC编写的C++项目,它给我带来了varargs方法的一些问题。

NB:该项目还应该使用非c++-11兼容的编译器进行编译,因此我不能在这里使用C++11语法。

GCC不加警告地接受以下代码(1):

代码语言:javascript
复制
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):

代码语言:javascript
复制
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):

代码语言:javascript
复制
 ./ootree.h:444:30: warning: 'va_start' has undefined behavior with reference types [-Wvarargs]

(2):

代码语言:javascript
复制
 ./ootree.h:476:30: warning: second parameter of 'va_start' not last named argument [-Wvarargs]

我可以轻松地用一个副本替换TreeIter引用(标准似乎要求我这么做),但我找不到一种简单的方法来修复(2),下面是一个显示行为的最小独立示例,这个程序不仅适用于gcc,而且也适用于clang,但是这些警告非常可怕.

代码语言:javascript
复制
#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);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-03 15:39:48

(2)的一个解决方案是显式地接受前2个参数,可能会提供一个1参数重载:

代码语言:javascript
复制
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);
}
票数 4
EN

Stack Overflow用户

发布于 2015-12-03 18:01:02

你可以将(2)改为

代码语言:javascript
复制
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(T(), 2, 4, 6);

甚至在第一个参数中添加一个虚拟标记:

代码语言:javascript
复制
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);

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34069843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档