繁体   English   中英

具有不同编译器的C ++和varargs

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM