操作符与表达式 3 (2.014)

无版本差异

[size=large]21 基本表达式(Primary Expressions)
标识符
.标识符
this
super
null
true
false
$

数字字法
字符文字
多个字符串文字
数组字法
AssocArrayLiteral
函数字法

Assert表达式
Mixin表达式
Import表达式
基本类型 .标识符
typeid ( 类型 )
Is表达式
( 表达式 )

21.1 .标识符
标识符 会在模块作用域内进行查找,而不是在当前词法的嵌套作用域内。

21.2 this
在非静态成员函数内,this 转换成对调用此函数的对象的引用。如果此对象是一个结构的实
例,则么 this 将会是该实例的指针。如果成员函数是显式地通过引用 typeof(this) 调用的,会生成一个非虚函数调用:

class A
{
char get() { return 'A'; }
char foo() { return typeof(this).get(); }
char bar() { return this.get(); }
}
class B : A
{
char get() { return 'B'; }
}
void main()
{
B b = new B();
b.foo(); // 返回 'A'
b.bar(); // 返回 'B'
}

21.3 super
super 等同于 this,除了它被类型转换成 this 的基类。如果不存在相应的基类,就会被认为是错误。在结构成员函数里使用 super 是错误的。(只有 Object 类没有基类。)super 不允许出现在结构的成员函数中。如果成员函数是显式地通过引用 super 调用的,会生成一个
非虚函数调用。

21.4 null
关键字 null 用于表示指针、函数指针、委托、动态数组、关联数组和类对象的空值。如果
它还没有被转换到某个类型,它就会被指定类型 (void *),而且对于指针、函数指针、委托
等等,将其转换成 null 值都是准确的转换。在它被转换到某个类型后,这个转换是隐式
的,但不再准确。

21.5 true, false
它们是 bool 类型,在转换到整数类型时,它们相应地变成 1 和 0。

21.6 字符字法(Character Literals)
字符字法指的是单个字符,并且类型是 char、wchar 或者 dchar 中的某一个。如果文字是
一个 \u 转义序列,对应类型就是 wchar。如果文字是一个 \U 转义序列,对应类型就是
dchar。否则,它的类型是能够容纳它的最小的类型。

21.7 字符串字法
多个字符串文字:
单个字符串文字
多个字符串文字 单个字符串文字

21.8 数组字法
数组字法:
[ 实参列表 ]
数组字法指的是一个处于方括号 [ 和 ] 之间,以逗号隔开的 赋值表达式 列表。赋值表达
式 组成了静态数组的元素,数组的长度就是元素的数目。第一个元素的类型代表了所有元
素的类型,并且所有元素隐式转换成该类型。如果该类型是一个静态数组,则它就被转换成
一个动态数组。
[1,2,3]; // 类型是 int[3],有元素: 1,2 和 3
[1u,2,3]; // 类型是 uint[3],有元素:1u,2u 和 3u

如果在 实参列表 里的参数有一个是 表达式元组,那么该 表达式元组 的元素将被插入进
来代替元组而成为参数。

21.9 关联数组字法
关联数组字法:
[ 多个键值对 ]
多个键值对:
单个键值对
单个键值对 , 多个键值对
单个键值对:
键表达式 :值表达式
键表达式:
条件表达式
值表达式:
条件表达式
关联数组字法指的是一个处于方括号 [ 和 ] 之间,以逗号隔开的“键:值”对列表。此列表
不能为空。第一个键的类型代表了所有键的类型,而其它剩余的所有键都会隐式转换成该类
型。第一个值的类型代表了所有键的类型,而其它剩余的所有值都会隐式转换成该类型。关
联数组字法 不能用于静态初始化。
[21u:"he",38:"ho",2:"hi"]; // 类型为 char[2][uint],同时键为 21u, 38u 和 2u
// 而值为 "he", "ho" 和 "hi"
如果在 键值对 里的有一个键或值是一个 表达式元组,那么这个 表达式元组 的元素将被
插入进来代替该元组而成为参数。

21.10 函数字法

function 类型
可选的
( 形参列表 )可选的
函数体
delegate 类型可选的 ( 形参列表 )可选的 函数体
( 形参列表 ) 函数体
函数体
有了 函数字法,就可以直接将匿名函数和匿名委托嵌入到表达式中。类型是函数或委托的
返回类型,如果被忽略的话,则会根据 返回语句(位于 函数体里)来进行推断。( 参数列
表 ) 是传递给函数的参数。如果忽略的话,会被认为是空参数列表 ()。函数字法的类型是
指向函数或者委托的指针。如果忽略关键字 function 或者 delegate,则默认是 delegate。

例如:
int function(char c) fp; // 声明函数指针
void test()
{
static int foo(char c) { return 6; }
fp = &foo;
}

等同于:
int function(char c) fp;
void test()
{
fp = function int(char c) { return 6;} ;
}

而:
int abc(int delegate(long i));
void test()
{ int b = 3;
int foo(long c) { return 6 + b; }
abc(&foo);
}

等同于:
int abc(int delegate(long i));
void test()
{ int b = 3;
abc( delegate int(long c) { return 6 + b; } );
}

而下面的内容则是推断出返回类型为 int:
int abc(int delegate(long i));
void test()
{ int b = 3;
abc( (long c) { return 6 + b; } );
}

匿名委托的行为就像任意的语句文字。例如,下面的 loop 可以执行任何语句:
double test()
{ double d = 7.6;
float f = 2.3;
void loop(int k, int j, void delegate() statement)
{
for (int i = k; i < j; i++)
{
statement();
}
}
loop(5, 100, { d += 1; } );
loop(3, 10, { f += 3; } );
return d + f;
}

与 嵌套函数 相比,function 形式类似于静态或者非嵌套函数,而 delegate 形式类似于非静态嵌套函数。换句话说,委托字法可以访问它外围函数的堆栈,而函数字法则不能。

21.11 断言表达式
断言表达式:
assert ( 赋值表达式 )
assert ( 赋值表达式 , 赋值表达式 )

断言会计算 表达式。如果结果为假,会抛出一个 AssertError 异常。如果结果为真,不会
抛出任何异常。如果 表达式 包含程序所依赖的任何副作用,就是一个错误。通过编译时的
命令行选项,编译器可以根本不对断言表达式求值。断言表达式的结果的类型是 void。断
言是 D 支持 契约式编程 的一个基础。

表达式 assert(0) 是一个特殊的情况;它表示它是不可达到的代码。如果它是可达到,则
会抛出一个 AssertError 异常,或者执行过程被中断(在 x86 处理器里,HLT 指令可以用来中断执行过程)。编程的优化和代码生成阶段可以假定它是不可达到的代码。

第二个 表达式,如果有的话,必须隐式可转换成类型 char[]。如果结果为 false,它就会
被求值,而字符串结果会被添加到 AssertError 的信息里。
void main()
{
assert(0, "an" ~ " error message");
}
当编译完成并且执行时,它会产生这样的信息:
Error: AssertError Failure test.d(3) an error message

21.12 Mixin 表达式
mixin ( 赋值表达式 )
赋值表达式 必须在编译时求值成一个常量字符串。该字符串的文本内容必须要可编译成一
个有效的赋值表达式,而且同样地被编译。
int foo(int x)
{
return mixin("x + 1") * 7; // 跟 ((x + 1) * 7) 一样
}

21.13 Import 表达式
import ( 赋值表达式 )
赋值表达式 必须在编译时求值成一个常量字符串。字符串的内容文本内容被认定为一个文
件名。文件会被读取,而此文件的实际内容会变成字符串文字。
void foo()
{
//输出文件 foo.txt 的内容
writefln( import("foo.txt") );
}

21.14 Typeid 表达式

typeid ( 类型 )
返回一个 TypeInfo(同 类型 相对应)类的实例。

21.15 Is表达式

Is表达式:
is ( 类型 )
is ( 类型 :类型特例 )
is ( 类型 == 类型特例 )
is ( 类型 标识符 )
is ( 类型 标识符 :类型特例 )
is ( 类型 标识符 == 类型特例 )

类型特例:
类型
typedef
struct
union
class
interface
enum
function
delegate
super

Is表达式 在编译时进行求值,并且用于检查合法的类型、比较类型的等效性、决定某种类
型可否隐式转换到了另一种类型,以及减少类型的字类型。Is表达式 的结果就是一个 int
类型的:如果条件不满足,就为 0;如果满足,则为 1。
类型 指的是要被测试的类型。它必须语句正确,不过不必语义正确。如果语义不正确,则
条件就不满足。

标识符 在条件满足的情况下被声明为结果类型的别名。仅能使用 标识符 形式的情形就是
如果 Is表达式 出现在 StaticIf条件 里。

类型特例(TypeSpecialization) 指的是要跟 类型(Type) 进行比较的类型。

Is表达式 的形式有:

1. is ( 类型 )
如果 类型 语义上正确(它必须是语句也正确),那么条件就满足。
alias int func(int); // func 是函数类型的别名
void foo()
{
if ( is(func[]) ) // 不满足,因为函数的数组
// 是不被允许的
writefln("satisfied");
else
writefln("not satisfied");
if (is([][])) // 错误,[][] 不是个语句有效的类型
...
}

2. is ( 类型 :类型特例 )
如果 类型 语义正确,则条件满足;它等同于或者可以被隐式转换成 类型特例。类
型特例 仅允许是一个 类型。
alias short bar;
void foo(bar x)
{
if ( is(bar : int) ) // 满足,因为 short 能够
// 隐式转换到 int
writefln("satisfied");
else
writefln("not satisfied");
}

3. is ( 类型 == 类型特例 )
如果 类型 语义正确,并且跟 类型特例 同类型,则条件满足。
如果 类型特例 属于
typedef、struct、union、class、interface、enum、function、delegate 中的某个, 那
么如果 类型 也是其中之一,则条件满足。
alias short bar;
typedef char foo;
void test(bar x)
{
if ( is(bar == int) ) // 不满足,因为 short 跟
// int 不同类型
writefln("satisfied");
else
writefln("not satisfied");
if ( is(foo == typedef) ) // 满足,因为 foo 是一个 typedef
writefln("satisfied");
else
writefln("not satisfied");
}

4. is ( 类型 标识符 )
如果 类型 语义正确,则条件满足。这样的话,标识符 被声明成为 类型 的一个别
名。
alias short bar;
void foo(bar x)
{
static if ( is(bar T) )
alias T S;
else
alias long S;
writefln(typeid(S)); // 输出 "short"
if ( is(bar T) ) // 错误,标识符 T 形式仅能
// 在 StaticIf条件 里面
...
}

5. is ( 类型 标识符 :类型特例 )
如果 类型 是 类型特例;或者如果 类型 是一个类并且 类型特例 是它的一个基类
或基接口,则条件满足。标识符 要被声明成 类型特例 的别名,或者声明成导出的
类型(如果 类型特例 依赖于 标识符 的话)。
alias int bar;
alias long* abc;
void foo(bar x, abc a)
{
static if ( is(bar T : int) )
alias T S;
else
alias long S;
writefln(typeid(S)); // 输出 "int"
static if ( is(abc U : U*) )
U u;
writefln(typeid(typeof(u))); // 输出 "long"
}

标识符 的类型被决定的方式类似于通过 模板参数特例化 来决定的模板参数类型。

6. is ( 类型 标识符 == 类型特例 )
如果 类型 语义正确,并且等于 类型特例,则条件满足。标识符 要被声明成 类型
特例 的别名,或者声明成导出的类型(如果 类型特例 依赖于 标识符 的话)。
如果 类型特例 属于
typedef、struct、union、class、interface、enum、function、delegate 中的某个, 那
么如果 类型 也是其中之一,则条件满足。此外,标识符 被设置成该类型的一个别
名:
关键字标识符 的别名类型
typedef 通过 typedef 定义出的 类型
struct 类型
union 类型
class 类型
interface 类型
super 基类和接口类型元组
enum 枚举类型
function 函数参数类型的 类型元组
delegate 委托函数类型
return 函数、委托或者函数指针返回类型
alias short bar;
enum E : byte { Emember }
void foo(bar x)
{
static if ( is(bar T == int) ) // 不满足,short 不是 int
alias T S;
alias T U; // 错误,T 没有被定义
static if ( is(E V == enum) ) // 满足,E 是一个 enum
V v; // v 被声明为一个字节
}
[/size]


.........
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值