2015-12-03 20 views
2

我想重新編譯一個用GCC編寫的C++項目來鏗鏘聲,它給了我一些可變參數方法的問題。C++&可變參數與不同的編譯器

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] 

我可以很容易地修復(1)通過用副本替換TreeIter引用(和標準似乎需要我做所以),但我沒有找到一個簡單的方法來解決(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); 
} 
+3

Clang是對的。請參閱[support.runtime]/3。 –

回答

4

的溶液(2)。將採取的第2個參數明確地,有可能提供一個單參數超載:

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); 
} 
+0

我使用了一個帶有模板參數而不是GValue的稍微修改過的版本,但是這解決了我的問題,謝謝:) – gabry

+0

@ Jarod42'gtk_list_store_set_valist'帶一個sentinel('-1'),所以總是有至少一個參數。 – ecatmur

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