[疑难] 请各位老大看一下这段代码有什么错误?
Colorful
2010-05-06
这段代码在 DMD 2.024 以前工作的很好。最近我重新拾起 D 语言,想不到怎么也不能通过最新版本的 DMD 编译器。它总是报
引用 Warning: statement is not reachable 。但我真的不知道问题出在哪里。还望各位老大给指点一下。
代码如下: /** * 该模块提供事件机制。 * License: BSD * Authors: Lucifer (786325481@QQ.com) * Copyright: Copyright (C) 2008 Lucifer. All rights reserved. */ module system.Event; import core.stdc.string; /** * 表示将处理事件的方法。 * Comments: 大多数情况下,我们应该使用这个模板。 * 如果想自定义事件参数,请使用 Event(T...) 。 */ public template EventHandler(T, TEventArg : EventArgs = EventArgs) { alias Event!(T, TEventArg) EventHandler; } /** * 用于声明事件的事件机制。 * Comments: 类似.NET的事件。 */ public struct Event(T...) { /// 事件所需要的委托类型。 alias void delegate(T) TDelegate; /// 事件所需要的函数指针类型。 alias void function(T) TFunction; private struct EventInfo { /* * 表明传进来的委托或函数指针类型。 */ enum Type { Delegate, Function } /* * 存储传进来的委托或函数指针 */ union { TDelegate delegateItem; TFunction functionItem; } Type type; /* * 构造函数。 */ public this(TDelegate dg) { type = Type.Delegate; delegateItem = dg; } /* * ditto */ public this(TFunction fn) { type = Type.Function; functionItem = fn; } /* * 比较两个 EventInfo 是否相等。 */ public const bool opEquals(ref const EventInfo other) { if(this.type == Type.Delegate) { return this.type == other.type && this.delegateItem == other.delegateItem; } else { return this.type == other.type && this.functionItem == other.functionItem; } } /* * 引发委托或函数指针调用。 */ public void invoke(T args) { if( type == Type.Delegate && delegateItem !is null ) { delegateItem(args); } else if( type == Type.Function && functionItem !is null ) { functionItem(args); } } } /* * 多数情况下,事件订阅的数量少于8个,甚至少于4个 * 这里我们把默认的事件订阅量设为2,且让它以2的倍数增长。 */ private const int defaultCapacity = 2; private int theSize; private EventInfo[] theList; /* * 注册委托或函数指针。 */ private void add(EventInfo eventInfo) { auto size = theList.length; if( size == 0 ) { theList.length = defaultCapacity; } if( size == theSize ) { theList.length = 2 * theList.length; } theList[theSize++] = eventInfo; } /* * 删除某个位置的委托或函数指针。 */ private void removeAt(int index) { theSize--; if( index < theSize ) { memmove(theList[index..$].ptr, theList[index+1..$].ptr, (theSize-index) * EventInfo.sizeof); } theList[theSize] = EventInfo.init; } /* * 查看是否有委托或函数指针注册。 */ private bool isEmpty() { return theSize == 0; } /* * 查找委托或函数指针在委托列表中的位置。 * 找到返回该位置;找不到则返回-1。 */ private int indexOf(EventInfo eventInfo) { for( auto i = 0; i < theSize; i++ ) { if( theList[i] == eventInfo ) { return i; } } return -1; } /** * 注册委托。 * Params: dg = 要注册的委托。 * 它的类型是 void delegate(T...) 。 * Comments: 该实现是线程安全和异常安全的。 * 当有异常发生时,直接返回。 */ public void add(TDelegate dg) in { assert( dg !is null ); } body { synchronized { auto eventInfo = EventInfo(dg); scope(failure) return; if( !isEmpty() ) { /* * 先查看是否包含该委托。 * 没有则注册,否则什么也不做。 */ if(indexOf(eventInfo) == -1) { add(eventInfo); } } else { /* * 到这里,没有委托注册,直接进行注册。 */ add(eventInfo); } } } /** * ditto */ public void add(TFunction fn) in { assert( fn !is null ); } body { synchronized { auto eventInfo = EventInfo(fn); scope(failure) return; if( !isEmpty() ) { if(indexOf(eventInfo) == -1) { add(eventInfo); } } else { add(eventInfo); } } } /** * 操作符重载。 */ public void opOpAssign(string op, T)(T obj) if(((op == "~=") || (op == "-=")) && (is(T:TDelegate) || is(T:TFunction))) { static if(op == "~=") { add(obj); } else static if(op == "-=") { remove(obj); } }; /** * 移除注册的委托。 * Params: dg = 要移除的委托。 * 它的类型是 void delegate(T...) 。 * Returns: 返回是否成功移除委托。 * 如果成功,返回 true 。否则,返回 false 。 * Comments: 该实现是线程安全和异常安全的。 * 当有异常发生时,直接返回。 */ public bool remove(TDelegate dg) in { assert( dg !is null ); } body { synchronized { auto eventInfo = EventInfo(dg); scope(failure) return false; auto index = indexOf(eventInfo); /* * 先找到要移除的委托在委托列表中的位置。 * 找到了就移除,否则什么也不做。 */ if( index != -1 ) { removeAt(index); } return index != -1; } } /** * ditto */ public bool remove(TFunction fn) in { assert( fn !is null ); } body { synchronized { auto eventInfo = EventInfo(fn); scope(failure) return false; auto index = indexOf(eventInfo); if( index != -1 ) { removeAt(index); } return index != -1; } } //alias remove opSubAssign; /** * 引发委托或函数指针调用。 * Comments: 该实现是线程安全和异常安全的。 */ public void invoke(T args) { synchronized { for( auto i = 0; i < theSize; i++ ) { scope(failure) break; theList[i].invoke(args); } } } alias invoke opCall; /** * 比较两个 Event(T...) 是否相等。 */ public const bool opEquals(ref const Event!(T) other) { for(auto i = 0; i < theSize; i++) { if( theList[i] != other.theList[i] ) { return false; } } return true; } } /** * 包含事件数据的基类。 */ public class EventArgs { private static EventArgs theEmpty; public static this() { theEmpty = new EventArgs(); } public this() { } /** * 表示没有事件数据的事件。 */ public static EventArgs empty() { return theEmpty; } } unittest { class Button { Event!(Button) press; EventHandler!(Button, EventArgs) clicked; } int count = 0; int numeric = 0; void wasPressedA(Button b) { count++; } void clickedA(Button sender, EventArgs e) { numeric++; } void clickedB(Button sender, EventArgs e) { numeric++; } void wasPressedB(Button b) { count++; } Button b = new Button(); // 测试 add() b.press.add(&wasPressedA); // 测试 invoke() b.press(b); b.clicked.add(&clickedA); b.clicked(b, EventArgs.empty); assert( count == 1 ); assert( numeric == 1 ); b.press ~= &wasPressedB; b.press.invoke(b); b.clicked ~= (&clickedB); b.clicked.invoke(b, EventArgs.empty); assert( count == 3 ); assert( numeric == 3 ); // 测试 remove() b.press.remove(&wasPressedA); b.press(b); b.clicked.remove(&clickedA); b.clicked(b, EventArgs.empty); assert( count == 4 ); assert( numeric == 4 ); b.press -= &wasPressedB; b.press(b); b.clicked.remove(&clickedB); b.clicked(b, EventArgs.empty); assert( count == 4 ); assert( numeric == 4 ); } |
|
betty_betty2008
2010-05-06
记得JUNO 在D2.032(大概吧)时能顺利编译,后来的就不行了,也是报同样的奇怪错误.JUNO FORUM里到现在都未能解决,具体原因提到过,俺忘了(没记错的话,应该与const bool opEquals(ref const arg)有关),LZ可以进去参照一下,或许有小小提示吧
public const bool opEquals(ref const Event!(T) other) { for(auto i = 0; i < theSize; i++) { if( theList[i] != other.theList[i] ) { return false; } } return true; } } |
|
sleets
2010-05-06
警告不算是错误吧。
|
|
Colorful
2010-05-07
@betty_betty2008
具体原因可能有多方面。单独简单的操作符重载测试并没有问题。嵌套的就有一些问题。 @sleets 这个警告导致不能生成程序,郁闷。 |
|
betty_betty2008
2010-05-07
盼望LZ早日解决,到时分享一下,俺也可以再回到D2试着编译一下JUNO.
|
|
sleets
2010-05-07
我这里似乎没问题,用的 http://xwall.googlecode.com/files/dmd-r471_tango-r5437_phobos-1060_d2-2045_20100507_A.7z , 昨天似乎用的版本也比dmd2.043高,也编译通过了。 并且只有加了-wi参数的时候才有Warning: statement is not reachable。
全部单元测试运行通过。 |
|
Colorful
2010-05-07
@sleets
老兄,按照你说的方法果然通过编译和单元测试。 启用警告的作用何在呢? |
|
betty_betty2008
2010-05-07
sleets 写道 我这里似乎没问题,用的 http://xwall.googlecode.com/files/dmd-r471_tango-r5437_phobos-1060_d2-2045_20100507_A.7z , 昨天似乎用的版本也比dmd2.043高,也编译通过了。 并且只有加了-wi参数的时候才有Warning: statement is not reachable。
全部单元测试运行通过。 哥们:DWT2/draw2D例子UML 运行需要icuuc38.dll,这玩意在哪找?GOOGLE百度都不行.. |
|
sleets
2010-05-07
http://xwall.googlecode.com/files/icu38.7z
|