知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070418
点击下面网址查看原文:
http://www.d-programming-language-china.org
by: uFramer uframer@sina100.com
author: D语言论坛 http://www.d-programming-language-china.org
from: http://www.digitalmars.com/d/expression.html
version: 基于D 1.013 (Apr 19, 2007)
C 和 C++ 程序员会发现 D 中的表达式很熟悉,另外还有一些有意思的扩充。
表达式用来计算多个值并返回一个特定类型的值。随后,所得的值可以被用于赋值、测试或被忽略。表达式也可能有副作用。
StringLiterals:
StringLiteral
StringLiterals StringLiteral
ArgumentList:
AssignExpression
AssignExpression , ArgumentList
求值顺序
除非另外指定,D 的实现可以以任何顺序对表达式中的各个部分求值。如果没有额外指定,就不能依赖于求值的顺序。例如,下面的代码是非法的:
i = ++i;
c = a + (a = b);
func(++i, ++i);
如果编译器能够确定表达式的值是依赖于求值顺序的话,它将报告一个错误(但这不是必须的)。检测这种错误的能力是实现的质量方面的问题。
表达式
先计算‘,’左面的操作数,然后计算右面的操作数。表达式的类型是右面的操作数的类型,表达式的结果是右面的操作数的结果。
The left operand of the , is evaluated, then the right operand is evaluated. The type of the expression is the type of the right operand, and the result is the result of the right operand.
赋值表达式
AssignExpression:
ConditionalExpression
ConditionalExpression = AssignExpression
ConditionalExpression += AssignExpression
ConditionalExpression -= AssignExpression
ConditionalExpression *= AssignExpression
ConditionalExpression /= AssignExpression
ConditionalExpression %= AssignExpression
ConditionalExpression &= AssignExpression
ConditionalExpression |= AssignExpression
ConditionalExpression ^= AssignExpression
ConditionalExpression ~= AssignExpression
ConditionalExpression <<= AssignExpression
ConditionalExpression >>= AssignExpression
ConditionalExpression >>>= AssignExpression
右面操作数的类型会被隐式地转换为左面操作数的类型,并赋给左面的操作数。结果的操作数的类型是左值得类型,结果的值是赋值后左值的值。
左面的操作数必须是左值。
1 赋值运算符表达式
如:
在语义上等价于:
差别是操作数 a 只计算一次。
条件表达式
条件表达式:
OrOr表达式
OrOr表达式 ? 表达式 : 条件表达式
第一个表达式会被转换为布尔型,并被计算。如果结果为真,就计算第二个表达式,所得到的结果就是条件表达式的结果。如果结果为假,就计算第三个表达式,所得到的结果就是条件表达式的结果。如果第二个或者第三个表达式是 void 型的,返回的类型就是 void 。否则,第二个和第三个表达式的类型会被隐式地转换为一个它们的公共类型,并成为条件表达式结果的类型。
OrOr 表达式
OrOr表达式:
AndAnd表达式
OrOr表达式 || AndAnd表达式
OrOr 表达式的返回类型是布尔型,例外是当右边的操作数为 void 时,结果会是 void 型。
OrOr 表达式计算它左面的操作数。如果左面操作数在转型到布尔型后,结果为真,就不会计算右面的操作数。如果 OrOr 表达式结果的类型是布尔型,则表达式的结果就为真。如果左面操作数为假,就计算右面的操作数。如果 OrOr 表达式是布尔型的,则结果就是右面的操作数转型为布尔型后的结果。
AndAnd 表达式
AndAnd 表达式
Or表达式
AndAnd表达式 && Or表达式
AndAnd 表达式的返回类型是布尔型,例外是当右边的操作数为 void 时,结果会是 void 型。
AndAnd 表达式计算它左面的操作数。如果左面操作数在转型到布尔型后,结果为假,就不会计算右面的操作数。如果 AndAnd 表达式结果的类型是布尔型,则表达式的结果就为假。如果左面操作数为真,就计算右面的操作数。如果 AndAnd 表达式是布尔型的,则结果就是右面的操作数转型为布尔型后的结果。( 本文出处: http://www.d-programming-language-china.org )
按位表达式
按位表达式对它们的操作数按位运算。它们的操作数必须是正数类型的。首先,会应用默认的正数提升。然后,执行按位运算。
1 Or 表达式
操作数之间执行‘或’运算。
2 Xor 表达式
操作数之间执行‘异或’运算。
And 表达式
AndExpression:
CmpExpression
AndExpression & CmpExpression
操作数之间执行‘与’运算。
Compare Expressions
CmpExpression:
EqualExpression
IdentityExpression
RelExpression
InExpression
相等 Expressions
EqualExpression:
ShiftExpression
ShiftExpression == ShiftExpression
ShiftExpression != ShiftExpression
ShiftExpression is ShiftExpression
ShiftExpression !is ShiftExpression
相等表达式比较相等运算符(==)或不等运算符(!=)的两个操作数。结果的类型是布尔型。在比较之前,操作数会通过常用的转换转型为它们的一个公共类型。
如果操作数是整数值或者指针,相等被定义按位精确匹配。结构的相等是指按位精确匹配(检查包括由于对齐而造成的空洞,通常它们会在初始化时被设为零)。浮点数的相等更复杂。-0 和 +0 相等。如果两个操作数都是 NAN ,则 == 和 != 运算都会返回假。其他情况下,按位比较相等性。( 本文出处: http://www.d-programming-language-china.org )
对于复数来说,相等被定义为等价于:
x.re == y.re && x.im == y.im
不相等被定义为等价于:
x.re != y.re || x.im != y.im
对于类和结构对象而言,表达式(a == b)被重写为 a.opEquals(b), (a != b)被重写为 !a.opEquals(b)
至于静态和动态数组,相等被定义为数组长度相等,并且对应的元素都相等。
同一表达式
IdentityExpression:
ShiftExpression is ShiftExpression
ShiftExpression !is ShiftExpression
is 用于比较同一性。如果要比较非同一性,使用 e1 !is e2 。结果的类型是布尔型。在比较之前,操作数会通过常用的转换转型为它们的一个公共类型。
如果操作数不是类对象、静态或动态数组,同一性被定义为等价于相等性。( 本文出处: http://www.d-programming-language-china.org )
对于类对象来说,同一性被定义为引用指向同一个对象。可以使用 is 比较 null 类对象。
对于静态和动态数组来说,同一性被定义为指向相同的数组元素。
同一运算符 is 不能被重载。
关系表达式
RelExpression:
ShiftExpression
ShiftExpression < ShiftExpression
ShiftExpression <= ShiftExpression
ShiftExpression > ShiftExpression
ShiftExpression >= ShiftExpression
ShiftExpression !<>= ShiftExpression
ShiftExpression !<> ShiftExpression
ShiftExpression <> ShiftExpression
ShiftExpression <>= ShiftExpression
ShiftExpression !> ShiftExpression
ShiftExpression !>= ShiftExpression
ShiftExpression !< ShiftExpression
ShiftExpression !<= ShiftExpression
首先,会对操作数应用整数提升。关系表达式返回结果的类型是布尔型。
对于类对象来说,Object.opCmp() 的结果构成了左操作数,0 构成了右操作数。关系表达式 (o1 op o2) 的结果是:
如果对象为 null,进行比较就是错误。
对于静态和动态数组来说,关系 op 的结果是操作符应用到数组中第一个不相等的元素的结果。如果两个数组相等,但是长度不同,较短的数组“小于”较长的数组。( 本文出处: http://www.d-programming-language-china.org )
整数比较
如果两个操作数都是整数类型,就会进行整数比较。
Integer comparison operators | Operator | Relation |
| < | less |
| > | greater |
| <= | less or equal |
| >= | greater or equal |
| == | equal |
| != | not equal |
如果 <、<=、> 或 >= 表达式中一个操作数为有符号数,另一个操作数为无符号数,会被视为错误。可以使用类型转换将两个操作数转型为同是有符号数或同是无符号数。
浮点指针比较
如果操作数其一或两者都是浮点指针,则执行浮点指针比较。
任何有实用价值的浮点操作都必须支持 NAN 值。尤其关系运算符要支持 NAN 操作数。浮点数的关系运算的结果可以是小于、大于、等于或未定义(未定义的意思是有操作数为 NAN )。这意味着有 14 可能的比较条件:
浮点数比较运算符
Floating point comparison operators | Operator | Greater Than | Less Than | Equal | Unordered | Exception | Relation |
| == | F | F | T | F | no | equal |
| != | T | T | F | T | no | unordered, less, or greater |
| > | T | F | F | F | yes | greater |
| >= | T | F | T | F | yes | greater or equal |
| < | F | T | F | F | yes | less |
| <= | F | T | T | F | yes | less or equal |
| !<>= | F | F | F | T | no | unordered |
| <> | T | T | F | F | yes | less or greater |
| <>= | T | T | T | F | yes | less, equal, or greater |
| !<= | T | F | F | T | no | unordered or greater |
| !< | T | F | T | T | no | unordered, greater, or equal |
| !>= | F | T | F | T | no | unordered or less |
| !> | F | T | T | T | no | unordered, less, or equal |
| !<> | F | F | T | T | no | unordered or equal |
注意:
1 对于浮点指针比较运算符来说,(a !op b) 并不等价于 !(a op b) 。
2 “未定义”的意思是有操作数为 NAN 。
3 “异常”的意思是如果有操作数是 NAN ,则抛出 Invalid 异常。并不味着抛出异常,可以用std.c.fenv函数检查异常。
In 表达式
InExpression:
ShiftExpression in ShiftExpression
可以检测一个元素是否在关联数组中:
int foo[char[]];
……
if ("hello" in foo)
……
in 表达式同关系表达式 <、<= 等有相同的优先级。如果查找的元素不在数组内就返回null,否则返回元素的位置。
移位表达式
ShiftExpression:
AddExpression
ShiftExpression << AddExpression
ShiftExpression >> AddExpression
ShiftExpression >>> AddExpression
操作数必须是整数类型,并且会使用常用的整数提升。结果的类型是左操作数提升后的类型。结果的值是左操作数移动右操作数指定的位得到的值。
<< 是左移,>> 是有符号右移(译注:也叫算术右移)。>>> 是无符号右移。(译注:也叫逻辑右移)
如果要移动的位数超过了左操作数的位数,会被认为是非法的:
和表达式
AddExpression:
MulExpression
AddExpression + MulExpression
AddExpression - MulExpression
CatExpression
如果操作数是整数类型,会应用整数提升,然后会通过常用的算术转换提升为它们的公共类型。
如果有操作数为浮点类型,另一个操作数会被隐式地转换为浮点类型,然后会通过常用的算术转换提升为它们的公共类型。( 本文出处: http://www.d-programming-language-china.org )
如果运算符是 + 或 - ,第一个操作数是指针,并且第二个操作数是整数类型,结果的类型就是第一个操作数的类型,结果的值是指针加上(或减去)第二个操作数乘以指针所指类型的大小得到的值。
如果指针所指的类型是 bit ,结果的值是第二个操作数除以 8 后与指针相加得到的指。如果第二个操作数不能被 8 整除,会被视为非法。
bit* p; p += 1; // 错误,1%8 不等于零 p += 8; // ok
如果第二个操作数是指针,第一个操作数是整数类型,并且运算符是 + ,会按照上面所说的方式进行指针运算,只不过操作数的顺序反过来。
浮点操作数的和表达式不是可结合的。
Cat 表达式
CatExpression:
AddExpression ~ MulExpression
Cat表达式连接数组,结果是一个动态数组。数组成员的类型必须相同。如果操作数其一是数组,另外的是数组成员类型,该数组成员会被转换成包含该数组成员的长度为1的数组,然后执行数组连接操作。
积表达式
MulExpression:
UnaryExpression
MulExpression * UnaryExpression
MulExpression / UnaryExpression
MulExpression % UnaryExpression
操作数必须是算术类型。先会执行整数提升,然后会通过常用的算术转换提升为它们的公共类型。
对于整数操作数来说,*、/ 和 % 对应于乘、除和取模运算。对于乘运算,会忽略溢出,结果会简单地截取为整数类型。如果除或者取模运算的右操作数为 0 ,会抛出一个 DivideByZero 异常。( 本文出处: http://www.d-programming-language-china.org )
对于浮点操作数来说,各种运算同对应的 IEEE 754 浮点运算相同。取模运算只能用于实数类型,不能用于虚数或者复数类型。
浮点数的积表达式不是可结合的。
%运行算符用于整数操作,如果操作数是正数则结果也是正数,otherwise the sign of the result is implementation defined.
一元表达式
UnaryExpression:
PostfixExpression
& UnaryExpression
++ UnaryExpression
-- UnaryExpression
* UnaryExpression
- UnaryExpression
+ UnaryExpression
! UnaryExpression
~ UnaryExpression
( Type ) . Identifier
NewExpression
DeleteExpression
CastExpression
NewAnonClassExpression
New 表达式
NewExpression:
NewArguments Type [ AssignExpression ]
NewArguments Type ( ArgumentList )
NewArguments Type
NewArguments ClassArguments BaseClasslistopt { DeclDefs }
NewArguments:
new ( ArgumentList )
new ( )
new
ClassArguments:
class ( ArgumentList )
class ( )
class
New 表达式用来在垃圾收集堆(默认情况)上或使用类或结构指定的分配器分配内存。
在为多维数组分配内存时,声明按照同读取前缀数组声明顺序相同的顺序读取声明。
char[][] foo; // 字符串动态数组
...
foo = new char[][30]; // 分配 30 个字符串数组
上面的数组分配也可以写成这样:( 本文出处: http://www.d-programming-language-china.org )
foo = new char[][](30); // allocate array of 30 strings
分配嵌套数组,可以使用多参数:
int[][][] bar;
...
bar = new int[][][](5,20,30);
等价于:
bar = new int[][][5];
foreach (ref a; bar)
{
a = new int[][20];
foreach (ref b; a)
{
b = new int[30];
}
}
If there is a new ( ArgumentList ), then those arguments are passed to the class or struct specific allocator function after the size argument.
If a NewExpression is used as an initializer for a function local variable with scope storage class, and the ArgumentList to new is empty, then the instance is allocated on the stack rather than the heap or using the class specific allocator.
Delete Expressions
DeleteExpression:
delete UnaryExpression
If the UnaryExpression is a class object reference, and there is a destructor for that class, the destructor is called for that object instance.( 本文出处: http://www.d-programming-language-china.org )
Next, if the UnaryExpression is a class object reference, or a pointer to a struct instance, and the class or struct has overloaded operator delete, then that operator delete is called for that class object instance or struct instance.( 本文出处: http://www.d-programming-language-china.org )
Otherwise, the garbage collector is called to immediately free the memory allocated for the class instance or struct instance. If the garbage collector was not used to allocate the memory for the instance, undefined behavior will result.
If the UnaryExpression is a pointer or a dynamic array, the garbage collector is called to immediately release the memory. If the garbage collector was not used to allocate the memory for the instance, undefined behavior will result.
The pointer, dynamic array, or reference is set to null after the delete is performed.
If UnaryExpression is a variable allocated on the stack, the class destructor (if any) is called for that instance. Neither the garbage collector nor any class deallocator is called.( 本文出处: http://www.d-programming-language-china.org )
转型表达式
CastExpression:
cast ( Type ) UnaryExpression
Cast表达式转换一元表达到类型。
cast(foo) -p; // (-p) 转型为 foo
(foo) - p; // foo 减去p
任何从类引用到派生类引用的转换都会执行运行时检查以确保转型是适当的,如果不适当,结果就是null。这种行为等价于 C++ 中的 dynamic_cast 运算符。
class A { ... }
class B : A { ... }
void test(A a, B b)
{
B bx = a; // 错误,需要类型转换
B bx = cast(B) a; // 如果 a 不是 B 类型,bx 就为 null
A ax = b; // 不需要类型转换
A ax = cast(A) b; // 不需要向上类型转换的运行时检查
}
如果想要检测一个对象 o 是否是类 B 的一个实例,可以使用转型:
if (cast(B) o)
{
// o 是 B 的一个实例
}
else
{
// o 不是 B 的一个实例
}
Casting a floating point literal from one type to another changes its type, but internally it is retained at full precision for the purposes of constant folding.
void test()
{( 本文出处: http://www.d-programming-language-china.org )
real a = 3.40483L; real b; b = 3.40483; // literal is not truncated to double precision assert(a == b); assert(a == 3.40483); assert(a == 3.40483L); assert(a == 3.40483F); double d = 3.40483; // truncate literal when assigned to variable assert(d != a); // so it is no longer the same const double x = 3.40483; // assignment to const is not assert(x == a); // truncated if the initializer is visible
}
Casting a value v to a struct S, when value is not a struct of the same type, is equivalent to:
S(v)
后缀表达式
PostfixExpression:
PrimaryExpression
PostfixExpression . Identifier
PostfixExpression . NewExpression
PostfixExpression ++
PostfixExpression --
PostfixExpression ( )
PostfixExpression ( ArgumentList )
IndexExpression
SliceExpression
索引表达式
IndexExpression:
PostfixExpression [ ArgumentList ]
后缀表达式 会被计算。如果 后缀表达式 的类型为静态或者动态数组,数组的长度赋给符号$。
如果后缀表达式是表达式Tuple,符号$就是tuple的长度
参数列表 有自己独立的声明作用域,$ 只出现在这个作用域中。
If PostfixExpression is an ExpressionTuple, then the ArgumentList must consist of only one argument, and that must be statically evaluatable to an integral constant. That integral constant n then selects the nth expression in the ExpressionTuple, which is the result of the IndexExpression. It is an error if n is out of bounds of the ExpressionTuple.
切片表达式
SliceExpression:
PostfixExpression [ ]
PostfixExpression [ AssignExpression .. AssignExpression ]
后缀表达式会被计算。如果后缀表达式 的类型为静态或者动态数组,会隐式地声明变量 length (还有特殊变量$),并将数组的长度赋给它。赋值表达式 有自己独立的声明作用域,length (和$) 只出现在这个作用域中。
第一个 赋值表达式 是切片的闭的下界,第二个 赋值表达式 是切片的开的上界。(译注:也就是 [...) ,学过数学的都知道,呵呵)。表达式的结果是 后缀表达式 数组的一个切片。( 本文出处: http://www.d-programming-language-china.org )
如果使用[ ], 切片就是整个数组长。
切片的类型是后缀表达式成员类型的动态数组。
If PostfixExpression is an ExpressionTuple, then the result of the slice is a new ExpressionTuple formed from the upper and lower bounds, which must statically evaluate to integral constants. It is an error if those bounds are out of range.
基本表达式
PrimaryExpression:
标志符
.标志符
this
super
null
true
false
数值文字量
字符文字量
字符串文字量
数组文字量
函数文字量
断言表达式
Mixin表达式
Import表达式
基本类型 . 标志符
typeid ( 类型 )
IsExpression
(Expression)
Identifier
.Identifier
this
super
null
true
false
$
NumericLiteral
CharacterLiteral
StringLiterals
ArrayLiteral
FunctionLiteral
AssertExpression
MixinExpression
ImportExpression
BasicType . Identifier
typeid ( Type )
IsExpression
( Expression )
1 .标志符
会在模块作用域内查找 标志符 ,而不是在当前词法的嵌套作用域内。
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'
}
3 super
super等同this, 例外是转换到this的基类时。如果不存在相应的基类,就会被认为是错误。super 不允许出现在结构的成员函数中(只有类对象没有基类)。如果成员函数是显式地通过引用 super 调用的,会生成一个非虚函数调用。( 本文出处: http://www.d-programming-language-china.org )
4 null
关键字 null 表示空指针,函数指针,委托,动态数组,关联数组和类对像;如果未转换到其他类型,它的类型是 (void *) ,并精确转换到空值指针,函数指针,委托等。类型转换后,是隐式,但不是长精确。
5 true, false
它们都是 bool类型,转换到整型后值分别为 1 和 0
6 字符文字量
字符文字量是单个的字符,类型是 char、 wchar 或者 dchar 。如果文字量是 \u 转义序列,类型就是 wchar 。如果文字量是 \U 转义序列,类型就是 dchar 。否则,它的类型是能够容纳它的最小的类型。
7 数组文字量
ArrayLiteral:
[ ArgumentList ]
数组文字量是用[和]包围,逗号,分隔的赋值表达式,结果是一个静态数组,长度就是数组成员数。第一个成员的类型就是所有成员的类型,所有成员隐式转换到该类型。如果是静态数组类型,就被转换为动态数组类型。
[1,2,3]; // type is int[3], with elements 1, 2 and 3
[1u,2,3]; // type is uint[3], with elements 1u, 2u, and 3u
If any of the arguments in the ArgumentList are an ExpressionTuple, then the elements of the ExpressionTuple are inserted as arguments in place of the tuple.( 本文出处: http://www.d-programming-language-china.org )
8 函数文字量
FunctionLiteral
function Type opt ( ArgumentList )opt FunctionBody
delegate Type opt ( ArgumentList )opt FunctionBody
( ArgumentList ) FunctionBody
FunctionBody
有了 函数文字量 ,就可以直接将匿名函数和匿名委托嵌入到表达式中。类型 是函数或委托的返回类型,如果忽略的话,就从函数体返回语句推断。( 参数列表 ) 是传递给函数的参数。如果忽略的话,会被认为是空参数列表 () 。函数文字量的类型是指向函数或者委托的指针。如果函数或委托的关键记号忽略,就默认是委托。
如:
int function(char c) fp; // 声明函数指针
void test()
{
static int foo(char c) { return 6; }
fp = &foo;
}
精确地等价于:( 本文出处: http://www.d-programming-language-china.org )
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, delegate { d += 1; } );
loop(3, 10, delegate { f += 1; } );
return d + f;
}
与 嵌套函数 相比,function 形式类似于静态或者非嵌套函数,而 delegate 形式类似于非静态嵌套函数。换句话说,委托文字量可以访问它外围函数的堆栈,而函数文字量则不能。
断言表达式
AssertExpression:
assert ( AssignExpression )
assert ( AssignExpression , AssignExpression )
断言会计算 表达式 。如果结果为假,会抛出一个 AssertError 异常。如果结果为真,不会抛出任何异常。如果 表达式 包含程序所依赖的任何副作用,就是一个错误。通过编译时的命令行选项,编译器可以根本不对断言表达式求值。断言表达式的结果的类型是 void 。断言是 D 支持 契约式编程 的一个基础。
The expression assert(0) is a special case; it signifies that it is unreachable code. Either AssertError is thrown at runtime if it is reachable, or the execution is halted (on the x86 processor, a HLT instruction can be used to halt execution). The optimization and code generation phases of compilation may assume that it is unreachable code.( 本文出处: http://www.d-programming-language-china.org )
The second Expression, if present, must be implicitly convertible to type char[]. It is evaluated if the result is false, and the string result is appended to the AssertError's message.
void main()
{
assert(0, "an" ~ " error message");
}
When compiled and run, it will produce the message:
Error: AssertError Failure test.d(3) an error message
Mixin Expressions
MixinExpression:
mixin ( AssignExpression )
The AssignExpression must evaluate at compile time to a constant string. The text contents of the string must be compilable as a valid AssignExpression, and is compiled as such.
int foo(int x)
{
return mixin("x + 1") * 7; // same as ((x + 1) * 7)
}
Import Expressions
ImportExpression:
import ( AssignExpression )
赋值表达式必须在编译时计算为常理字符串。文字内容被解释为文件名,读入文件,然后文件内容被精确转换为字符串文字量。
void foo()
{
// 打印出foo.txt的所有内容
writefln( import("foo.txt") );
}
Typeid 表达式
TypeidExpression:
typeid ( Type )
返回同 类型 对应的 TypeInfo 类的实例。( 本文出处: http://www.d-programming-language-china.org )
Is表达式
IsExpression:
is ( Type )
is ( Type : TypeSpecialization )
is ( Type == TypeSpecialization )
is ( Type Identifier )
is ( Type Identifier : TypeSpecialization )
is ( Type Identifier == TypeSpecialization )
TypeSpecialization:
Type
typedef
struct
union
class
interface
enum
function
delegate
super
is表达式在编译时求值,常用于检查是否有效类型,比较类型是否相等,决定一类型是否能隐式转换成其他类型, 和推断是否是某类型的子类型。不满足条件结果是int 0,否则结果是1
Type 就是用来测试的类型,必须语法正确,语义正确不是必须的。如果语义错误,就是不满足条件。
如果满足条件,Identifier 是结果类型的别名. Identifier形式只能用在is表达式出现在StaticIfCondition内的时候。
TypeSpecialization是被比较的类型。
is表达式有如下形式:( 本文出处: http://www.d-programming-language-china.org )
1 is ( Type )
语义正正确就满足条件(必须语法正确)
alias int func(int); // func 是函数类型的别名
void foo()
{
if ( is(func[]) ) // 不满足条件,因为数组不允许用于函数
printf("satisfied\n");
else
printf("not satisfied\n");
if (is([][])) // 错误, 语法上[][] 不是有效类型
...
}
2 is ( Type : TypeSpecialization )
如果Type语义正确,并能同于或能隐式转换到TypeSpecialization。TypeSpecialization必须是类型。
alias short bar;
void foo(bar x)
{
if ( is(bar : int) ) // satisfied because short can be
// implicitly converted to int
printf("satisfied\n");
else
printf("not satisfied\n");
}
3 is ( Type == TypeSpecialization )
如果Type语义正确,并且和TypeSpecialization类型相同。
如果TypeSpecialization是typedef struct union class interface enum function delegate 其中之一,Type是其中之一就是是满足条件。
alias short bar;
typedef char foo;
void test(bar x)
{
if ( is(bar == int) ) // not satisfied because short is not
// the same type as int
printf("satisfied\n");
else
printf("not satisfied\n");
if ( is(foo == typedef) ) // satisfied because foo is a typedef
printf("satisfied\n");
else
printf("not satisfied\n");
}
4 is ( Type Identifier )
Type语义正确就是满足条件,然后Identifier被声明为Type的别名。
alias short bar;
void foo(bar x)
{
static if ( is(bar T) )
alias T S;
else
alias long S;
writefln(typeid(S)); // prints "short"
if ( is(bar T) ) // error, Identifier T form can
// only be in StaticIfConditions
...
}
5 is ( Type Identifier : TypeSpecialization )
The condition is satisfied if Type is the same as or can be implicitly converted to TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type. TypeSpecialization is only allowed to be a Type.( 本文出处: http://www.d-programming-language-china.org )
alias short 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)); // prints "int"
static if ( is(abc U : U*) )
U u;
writefln(typeid(typeof(u))); // prints "long"
}
The way the type of Identifier is determined is analogous to the way template parameter types are determined by TemplateTypeParameterSpecialization.
6 is ( Type Identifier == TypeSpecialization )
The condition is satisfied if Type is semantically correct and is the same as TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type.
If TypeSpecialization is one of typedef struct union class interface enum function delegate then the condition is satisifed if Type is one of those. Furthermore, Identifier is set to be an alias of the type:
| keyword | alias type for Identifier |
| typedef | the type that Type is a typedef of |
| struct | Type |
| union | Type |
| class | Type |
| interface | Type |
| super | TypeTuple of base classes and interfaces |
| enum | the base type of the enum |
| function | TypeTuple of the function parameter types |
| delegate | the function type of the delegate |
| return | the return type of the function, delegate, or function pointer |
代码:
alias short bar;
enum E : byte { Emember }
void foo(bar x)
{
static if ( is(bar T == int) ) // not satisfied, short is not int
alias T S;
alias T U; // error, T is not defined
static if ( is(E V == enum) ) // satisified, E is an enum
V v; // v is declared to be a byte
}
( lastupdate:20070421 最新文章请访问http://www.d-programming-language-china.org )关于一大步成功社区:
yidabu提倡在交流中学习,在分享中提高
收集感兴趣的知识,写下心得,通过网络与别人一起分享
理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的
网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台