d区间原语错误消息

原文
我想出了个通用方法:
先写个验证器方法:

bool testInputRange(T)() {
	static assert(is(typeof(T.init.empty)));
	static assert(is(typeof(T.init.front)));
	static assert(is(typeof(T.init.popFront)));
	return true;
}//返回值不必要,但不重要

我们就可这样:

void f(T)(T x) if (isInputRange!T) { ... }
enum isInputRange(T) = is(typeof(testInputRange!T));
//是输入区间

很普通,但现在,替换为:

enum isInputRange(T) = is(typeof(testInputRange!T)) || testInputRange!T && false;

明显,testInputRange!T && false为假,而is(typeof(testInputRange!T)) || falseis(typeof(testInputRange!T))等价,虽然逻辑一样,但有更好错误消息.

struct S {}
f(S());

错误为:

range_check.d(12): Error: static assert:  `is(typeof(S().empty))` is false
//告诉了我们,没有`empty`函数.
range_check.d(10):        instantiated from here: `testInputRange!(S)`
range_check.d(4):        instantiated from here: `isInputRange!(S)`

问题是,没有一次报告所有问题.而front/popFront也未报告,错误消息,只提示了empty.
一种方法是:

void StaticAssert(alias x)() if (x) {}
bool testInputRange(T)() {
	StaticAssert!(is(typeof(T.init.empty)));
	StaticAssert!(is(typeof(T.init.front)));
	StaticAssert!(is(typeof(T.init.popFront)));
	return true;
}

现在错误消息中得到(12, 13, 14),行号,
上面的isInputRange不严格等价标准版输入区间.因此如想支持多实例,必须同样要求分发阶段.

posted @ 2022-01-05 21:00  zjh6  阅读(22)  评论(0)    收藏  举报  来源