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

时间:2015-12-03 15:28:57

标签: c++ gcc clang variadic-functions

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

NB :项目也应该使用非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 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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(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);