[疑难] 请各位老大看一下这段代码有什么错误?

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
Global site tag (gtag.js) - Google Analytics