2017-08-27 48 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]"); 
}