38用d编程条件编译
-unittest
单元测试.
in,out,invariant
没有-release
.
单元测试/合同用于程序正确性
.
模板只特化实际使用类型
.
void swap(T)(ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
unittest {
auto a = 'x';
auto b = 'y';
swap(a, b);
assert(a == 'y');
assert(b == 'x');
}
void swap(T : uint)(ref T lhs, ref T rhs) {
lhs ^= rhs;
rhs ^= lhs;
lhs ^= rh; // TYPO!
}
void main() {
}
原来认为^
比临时
的慢.但相反,现代微控器这种方法更慢.
unittest {
uint i = 42;
uint j = 7;
swap(i, j);
assert(i == 7);
assert(j == 42);
}
//单元测试,发现错误
d
的条件编译:
debug
version
static if,c++已有
is expression
__traits
开发期间,-调试
很有用.
debug a_conditionally_compiled_expression;
debug {
// ... 条件编译代码...
} else {
// ... 否则编译代码 ...
}
调试
size_t binarySearch(const int[] values, in int value) {
writefln("searching %s among %s", value, values);
if (values.length == 0) {
writefln("找不到%s", value);
return size_t.max;
}
immutable midPoint = values.length / 2;
writefln("考虑%s索引", midPoint);
if (value == values[midPoint]) {
writefln("found %s at index %s", value, midPoint);
return midPoint;
} else if (value < values[midPoint]) {
writefln("必在前半");
return binarySearch(values[0 .. midPoint], value);
} else {
writefln("必在后半");
return binarySearch(values[midPoint + 1 .. $], value);
}
}
在前面加上debug
,这样下次还可用.
debug writefln("%s not found", value);
dmd deneme.d -ofdeneme -w -debug
就可搞定了
只输出我想要的:
debug(binarySearch) writefln("%s not found", value);
dmd deneme.d -ofdeneme -w -debug=binarySearch
这样只调试这种块.
块也可以
debug(binarySearch) {
// ...
}
dmd deneme.d -w -debug=binarySearch -debug=stackContainer
多个调试块.
可以逐渐增加调试级:
debug import std.stdio;
void myFunction(string fileName, int[] values) {
debug(1) writeln("entered myFunction");
//1级.
debug(2) {//2级
writeln("the arguments:");
writeln(" file name: ", fileName);
foreach (i, value; values) {
writefln(" %4s: %s", i, value);
}
}
// ...实现函数...
}
void main() {
myFunction("deneme.txt", [ 10, 4, 100 ]);
}
//---
$ dmd deneme.d -w -debug=1
$ ./deneme
entered myFunction
将打印级数小的,级越大,越详细
version(tag) 和 version(level)
,类似debug
.
version(testRelease) /* ... an expression ... */;
version(schoolRelease) {
//此版本与学校发布相关
} else {
// ... 否则编译代码...
}
version(1) aVariable = 5;
version(2) {
// ... 2版本特征 ...
}
$ dmd deneme.d -w -version=record -version=precise_calculation
定义多个版本
完整预定义版本标志
none(禁用)
,all(允许)
代码块.
version(Windows) {
immutable newline = "\r\n";
} else version(Posix) {
immutable newline = "\n";
} else {
static assert(0, "不支持 OS");
}
用于确定系统的换行符.
import std.stdio;
debug(everything) {
debug = binarySearch;
debug = stackContainer;
version = testRelease;
version = schoolRelease;
}
void main() {
debug(binarySearch) writeln("binarySearch is active");
debug(stackContainer) writeln("stackContainer is active");
version(testRelease) writeln("testRelease is active");
version(schoolRelease) writeln("schoolRelease is active");
}
这些debug
与version
变量就像个集
一样,加进去.只要有其中一个,就可以调试了.就像调试集
/版本集
.
命令如下dmd deneme.d -w -debug=everything
.
static if
,编译时条件判断,只要是编译时已知的东西都可以用它.用来决定如何生成代码.逻辑表达式经常可以利用is
和双下划线trait
.
可在模块域
或类,构,模板
中出现static if
.也可以有if
语句.
简单例子:
import std.stdio;
struct MyType(T) {
static if (is (T == float)) {
alias ResultType = double;
} else static if (is (T == double)) {
alias ResultType = real;
} else {//
static assert(false, T.stringof ~ " is not supported");
}
ResultType doWork() {
writefln("The return type for %s is %s.",
T.stringof, ResultType.stringof);
ResultType result;
// ...
return result;
}
}
void main() {
auto f = MyType!float();
f.doWork();
auto d = MyType!double();
d.doWork();
}
只能用于浮
与双精
,返回类型取决于其中一个.
注意,编译时的比较都必须写static if
.如果不写static
,将把剩下的if
块插入进去.就与本意不一样了.
static assert
,编译时断定是否满足条件.如为假,程序直接退出.可出现在程序的任何域
中.
如上面程序,auto i = MyType!int();
,将会导致static assert "int is not supported"
.不支持.
如算法只适用于特定情况:
T myAlgorithm(T)(T value) {
static assert((T.sizeof % 4) == 0);
//要求T的大小是4的整数倍
// ...
}
调用时,如果为char
,就会失败.
这样,避免使用错误的类型,而产生可能的错误
了.
__traits
提供编译时类型和表达式
的信息.
编译器收集的.可以这样__traits(keyword, parameters)
关键词为要查的信息,参数为(类型/表达式).这些信息对模板非常有用
.
static if (__traits(isArithmetic, T)) {
// ... 算术类型...
} else {
// ... 不是 ...
}
//----
//类似,提供是否是符类型
import std.traits;
// ...
static if (isSomeChar!T) {
// ... char, wchar, 或 dchar ...
} else {
// ... 不是 ...
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现