2012-01-13 54 views
1

我正在做的事情,讓我更容易調用腳本語言(Lua)函數,一個想法是使用可變參數。有兩種方法可以做到這一點:如何將可變參數轉換爲容器類?

Call(int count, ...) 

Call(const char* args, ...) 

如printf。我認爲第一個維護起來會容易一些,所以我試圖通過製作一個包裝來管理參數類型。它看起來像這樣:

class ArgWrapper 
{ 
public: 
    ArgWrapper(); 

    ArgWrapper(const int& v) { val.i = v; type = INT; } 
    ArgWrapper(const bool& v) { val.b = v; type = BOOL; } 
    ArgWrapper(const float& v) { val.f = v; type = FLOAT; } 
    ArgWrapper(const double& v) { val.d = v; type = DOUBLE; } 

    operator int() { return val.i; } 
    operator bool() { return val.b; } 
    operator float() { return val.f; } 
    operator double() { return val.d; } 

    enum { 
     INT, 
     BOOL, 
     FLOAT, 
     DOUBLE 
    } type; 

    union 
    { 
     int i; 
     bool b; 
     float f; 
     double d; 
    } val; 
}; 

這工作得很好,很正常,但是當我真正嘗試做一個varadic論證建設這項工作,事實證明,這些值沒有實際鑄造。

void printArgs(int c, ArgWrapper...) 
{ 
    va_list ap; 
    va_start(ap, c); 

    for (int i = 0; i < c; i++) 
    { 
     ArgWrapper arg = va_arg(ap, ArgWrapper); 
     if (arg.type == arg.INT) std::cout << "integer - " << (int)arg << std::endl; 
     if (arg.type == arg.BOOL) std::cout << "boolean - " << std::boolalpha << (bool)arg << std::endl; 
     if (arg.type == arg.FLOAT) std::cout << "float - " << (float)arg << std::endl; 
     if (arg.type == arg.DOUBLE) std::cout << "double - " << (double)arg << std::endl; 
    } 

    va_end(ap); 
} 

... 

printArgs(4, 1337.0f, 18, 37.0, true); 

上述結果中的垃圾,而這工作完全正常:

printArgs(4, (ArgWrapper)1337.0f, (ArgWrapper)18, (ArgWrapper)37.0, (ArgWrapper)true); 

如何指定每個參數可變參數應該具有相同的常見的類型?

回答

4

當您使用C++ 03時,您無法使用,因爲使用c樣式省略號...的可變參數不以任何方式攜帶類型信息。這就是爲什麼像printf()這樣的東西使用格式說明符,因爲它需要一種方法來知道什麼東西要投入。

當您可以使用C++ 11時,您應該立即使用可變參數模板,這將使您的ArgWrapper等任何類型的幫助變得不必要。

0

時,如果你有一個C++編譯器,它支持從初始化列表功能C++ 11,你可以寫你的printArgs功能

#include <initializer_list> 

void printArgs(std::initializer_list<ArgWrapper> args) { 
    for (const ArgWrapper *arg = args.begin(), *end = args.end; arg != end; ++arg) { 
    /* process arg */ 
    } 
} 

,並調用它像

printArgs({ 4, 1337.0f, 18, 37.0, true }); 

這可以有時候比可變參數模板更容易。

0

可變參數模板救援:

template <typename ...Args> 
R call(int n, Args &&... args) 
{ 
    return printArgs(n, ArgWrapper(std::forward<Args>(args))...); 
} 

這是假設你printArgs函數必須實際使用C風格的可變參數。有理由和反對它;如果一切都是C++,你有幾個選擇。

相關問題