我的D程序中有一些相当奇怪的行为,我已经缩小到这个:
import std.algorithm;
import std.stdio;
import std.traits;
enum E { a, b, c };
struct S { E e; };
void main()
{
immutable(S)[] source = [ S(E.a), S(E.a), S(E.b) ];
foreach (e; EnumMembers!E)
{
size_t c = count!(x => x.e == e)(source);
writeln(e, " -> ", c);
}
}
我希望这个程序的输出符合以下几点:
a -> 2
b -> 1
c -> 0
但实际结果是:
a -> 2
b -> 2
c -> 2
奇怪的是,将for循环更改为foreach (e; [ E.a, E.b, E.c ])
会产生我预期的输出。使用foreach (e; [ EnumMembers!E ])
也会产生我预期的结果,所以很明显我使用EnumMemebers
的范围就是问题......我只是不知道为什么。
我显然做错了什么,但我不知道是什么,并希望得到一些见解。
我的编译器在Linux上是DMD64 D Compiler v2.059
。
编辑:这与GDC 4.6.3完全相同,因此它不能成为编译器错误。
编辑:将count
调用移至单独的函数:
size_t counte(Range)(E e, Range src)
{
return count!(x => x.e == e)(src);
}
并将c
的初始化更改为size_t c = counte(e, source);
,该程序可以正常运行。
答案 0 :(得分:3)
简短而不完整的答案可能有助于挖掘方向:
EnumMembers!T是一个类型元组(http://dlang.org/tuple.html - > Type Tuple),而不是表达式元组或数组。当您使用[EnumMembers!T]语法时,在编译时将元组用作初始化列表,并创建常规数组,从而提供预期的行为。
现在,如果你在foreach语句中按原样使用类型元组,那么事情就会变得有趣。元组有一个特殊情况foreach:http://dlang.org/statement.html - > Foreach over Tuples。并且在表达式类型元组的情况下(抱歉奇怪的措辞,但遗憾的是,这就是它在D中的命名)它并不真正创建一个变量 - 它只是用类型元组取代的表达式替换e的所有用法。
在这里我们去 - 在lambda中只用元组中的表达式替换,所以这个lambda不是委托的。我已检查过它的类型,它是“bool function(S x)pure nothrow”。猜猜它是在第一次使用时创建的,在lambda代码中记住e表达式,然后按原样使用它。
我需要其他人评论这是一个错误,错误或按预期工作。