2017-08-27 55 views
1

假設我有下面的可變參數函數,哪個作業是將來自塊的路徑連接在一起(每個塊可以是整型的索引,或者是字符串類型的節點) :D - 靜態如果在可變參數不能正常工作

string 
makePath(P...)(P path) 
{ 
    import std.conv; 
    import std.format; 

    string res; 
    foreach (piece; path) { 
     pragma(msg, typeof(piece).stringof); 
     static if (is(piece: size_t)) 
      res = res is null ? piece.to!string : format("%s[%s]", res, piece); 
     else if (is(piece: string)) 
      res = res is null ? piece : format("%s.%s", res, piece); 
     else 
      static assert(0); 
    } 
} 

如果我以後使用它像這樣:string path = makePath("foo", "bar"),不知何故代碼到達static assert(0);和編譯終止。這是最好奇的,但編譯實際上將string寫爲第一個參數的類型,儘管其他類型的代碼路徑已被採用。

更妙的是,使用makePath(12, 13)導致編譯器抱怨(約不兼容類型的intstring)和static assert行。這裏發生了什麼?

我在DMD和LDC上都試過這個。

+0

第一個'else if'應該延長爲'else static if'。這是你的原始代碼或只是在這裏的錯誤? –

+0

@ AdamD.Ruppe是的,這是原始代碼中的一個錯誤(現在你已經指出了一個非常愚蠢的代碼)。 – Michail

回答

1

is關鍵字是這裏的錯誤。 (這是一個相當混亂的關鍵詞,我覺得...)

我建議你使用std.traits模板來測試類型,最有覆蓋:https://dlang.org/phobos/std_traits.html

這是你的函數的一個工作版本:

string 
makePath(P...)(P path) 
{ 
    import std.conv; 
    import std.format; 
    import std.traits : isSomeString, isNumeric; 

    string res; 
    foreach (piece; path) { 
     static if (isNumeric!(typeof(piece))) 
      res = res is null ? piece.to!string : format("%s[%s]", res, piece); 
     else static if (isSomeString!(typeof(piece))) // Note, you were missing the 'static' on the 'else if' part 
      res = res is null ? piece : format("%s.%s", res, piece); 
     else 
      static assert(0); 
    } 
    return res; 
} 

unittest { 
    static assert(makePath("foo","bar") == "foo.bar"); 
    static assert(makePath("foo","bar",1) == "foo.bar[1]"); 
}