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");
}

这些debugversion变量就像个一样,加进去.只要有其中一个,就可以调试了.就像调试集/版本集.
命令如下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 {
        // ... 不是 ...
    }

有两个地方提供相关有用信息:一,_ _traits,二,std.traits中的模板.
参考1参考2

发布了440 篇原创文章 · 获赞 29 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/fqbqrr/article/details/104588781