赞
踩
值类型异常
是一个新的处理代码基
中不需要堆内存分配或运行时机制
来执行的替代路径
机制.它围绕从函数
中(基于类和结构
)抛异常
的新属性
设计的.
推导
属性可避免编译器过度写入
并抱怨
.
目前,D
语言中的异常
或需要几乎没有语言辅助
的显式类型
,或需要运行时信息
及展开库
来辅助它.
这两个
方法都不可取.相反,此DIP
旨在实现:
1,无(堆)
内存分配.
2,使用
标准的throw
和try catch
语句.
3,不直接给用户提供运行时库或信息
,这使它适合betterC
代码和资源
受限系统
.
4,不会引入在所有代码基
中都有侵入性
的新语法.
最好,允许删除throw,nothrow
及Throwable
子项的默认值
.
这些限制,允许在异常处理
和函数指针
不管用的时候在GPU
上的异常
工作.
@throws
属性的一个关键特征
是,一般可推导出它
.这与Java
类语言严重依赖IDE
支持来自动设置
列表中内容的校验异常
相反.
异常语法和机制
的替代方法
是错误返回或可选数据
.错误返回
可带错误码
.
该机制按标签联
实现.就性能而言,与同类
的错误
方法可最直接
的比较.
该设计源于HerbSutter
的零成本确定性异常
论文,EmilDotchevski
修改机制可见更多属性
.
使用HerbSutter
在他的论文中提出的表格
:
A
."错误"
流与"成功"
不同的是,两者都通过抛和抓
来抛和处理
.
B
.错误传播
和处理"是"
表示仅显式写入抓
,自动传播
未处理错误,很容易编写错误保留
及错误中立
函数.
对未处理
错误传播,除非调用者
显式写入非空
的throws
属性,"否"
是可见的.
C
.对非堆(都是栈分配
)是零成本和确定性
的是(Yes)
,静态类型
,除了标签联标识
外,不需要运行时信息
,空间/时间
成本等于返回
(标签联
,匹配原始表
中的其他值
),且(根据原始表
中的其他项目
)是完全确定
的.
BS
对该异常
处理风格的一些批评,可通过推导属性
来解决,除非在处理函数指针
或想犯错
时,否则不需要关心@throws
属性.
此DIP
添加了新的属性特征
及抛和抓
异常的机制.
由编译器内部存储类型
的集合
表示该属性
.有效类型
是从Throwable
继承的结构,类或接口
.
所有函数
都自动推导
属性,如果集合
不匹配提供的属性
,则将出错.
int add(int x, int y) {
return x + y;
}
上例,在不添加throws
属性时,表明需要推导
它.上例,它不会抛
,因此会有个空集
.可用代码
重写为@throws()
.
struct MyException { int someData; string lastThrow, originalThrow; } int add(int x, int y) { if (x == y) throw MyException(x + y); } int add2(int x, int y) { try { return add(x, y); } catch(MyException e) { stderr.writeln("Oh noes... something happened: ", e.originalThrow); return e.someData; } }
上例中,add
有按@throws(MyException)
设置的属性,而add2
将有@throws()
.这是因为add2
抓可从集合
中删除
的所有代码路径
中的异常
.
虽然throws
属性支持类
且确实会验证
,但它非常宽松
,不应影响
现有代码.
必须复制
而不是移动
基于结构
的异常,这是指成员数据
及引用计数
的内存完整性
期望复制构造器和析构器
.对内存
一致性,不必要的调用
,不会阻止
优化.
AtAtribute:
...
+ @ throws
+ @ throws ( ThrowsArgumentList|opt )
+ ThrowsArgumentList:
+ Type
+ Type ,
+ Type , ThrowsArgumentList
TraitsExpression:
+ getThrowSet
添加
了一个新属性
,而@throws
带可选的参数列表
.参数列表值的计算结果
,必须为从Throwable
继承的类或结构
.
所有不带参数列表
的@throws
属性的函数,都默认为推导
属性值.nothrow
属性等效于@throws()
,并且按用户
编写了新属性
对待.
无论是哪种属性,推导
都按语义
的一部分分析.如果已设置属性
且不等价
,则编译器将出错
.这算程序员错误.
等价检查
隐式转换类型限定符
,且在基于
类的机制中与父类子类
都相关.即,如果在属性列表
中设置了Throwable
,则在匹配Exception
时触发Exception
.
如果未提供函数体,类或接口虚
方法,则按@throws(Exception)
推导,这与当前行为
匹配,并计划按错误行为
删除它.
要获得抛集
,可用__traits(getThrowSet,symbol)
特征,可用它来生成try catch
语句,以从抛集
中删除类型
.
在@throws
属性中,提供异常
类型而不抛,不算错误
.
@throws
属性是个集合
.通过触发和抓
异常来添加或删除
值.
如果试抓
未在抛集
中表示的异常
,则应发出
警告.这可能是不必要的路径
,或更差,一条未记录
的路径.
如果使用条件编译
(CTFE
生成的代码或版本
)并收到此警告
,则应用所有可能异常
显式设置抛集
,而不是依赖推导
.
对类
,如果在抛集
中表示了个异常
,但它不是项
的父级
或等于项
,则不能删除
项.因为可能有仍可能抛的未知子
.
使用推导
,添加从集合
中删除
异常的示例
.
int toCall() /*@throws(MyException)*/ {
throw new MyException;
}
int caller() /*@throws()*/ {
int result;
try {
result = toCall();
} catch(MyException) {
result = 0xDEADBEEF;
}
return result;
}
抓所有异常
并不是个已解决
的问题,但未来可用模式匹配
来解决
.
此DIP
中引入
了一个新的利用
了新的@throws
属性来抛
和抓异常
的机制.
所有D函数
的返回类型
都有非空抛集
,且有等价于标签联
的结构成员
.但是,与普通
的标签联
不同,标签值
不基于可能选项列表
中的偏移
.
相反,应该基于一个,编译器可基于与使用位置
无关如全名哈希值
的符号
生成的整数值
.
如果非extern(D)
函数,在推导
中设置的抛集
中有其成员
,且在抛集
中有结构成员
算错误
.这是因为修改
了其他语言
无法表示的函数签名
.
此新机制
不需要更改语法
,基于类的异常
可能会重写
其实现以利用它,而不需要运行时库
来抛和抓
.
对结构
,该机制
与三个成员相关.两个
识别抛位置
.第三个用作标签联的标签值
,并考虑结构的非零大小
,并允许取用来标识类型
的标签.
抛位置成员
是lastThrow
和originalThrow
.如果已按非null
设置originalThrow
成员,且正在抛它,则相反设置lastThrow
成员.
即,如果生成栈跟踪
,则最多
仅包含两个函数调用
.不能来在原始抛
和上次抓
的位置间创建全栈跟踪
.这些成员设置为在ROM
中存储的并应包含
全限定模块名和行号
的串.如,"my.mod.ule:102"
.
标签值
使用tag
的成员名.它必须是uint
或ulong
,且是第一个字段
.此字段
的目的是在复制
调用栈时,允许结构
有效地为零大小.
最初
可能是无用
的,但它确实有优化
潜力.对未抓
的值类型异常
,这样无需检查重抛
数据,可用单个else
块来重抛,不需要调用复制构造器
,析构器或后复制
的东西.
如果函数
中未抓值类型异常
,则在调用者函数
中,编译器会自动
重抛它,但(如果有)不会
更改lastThrow
成员.
该机制
应该尽量便宜,它是为了在抛异常
的附近抓
.一般由库作者
使用,除非资源受限
,否则不适合应用作者
.
它不需要堆分配
,且必须保证在调用栈
中清理函数区间
内的变量
.
建议弃用nothrow
关键字,以支持@throws()
语法,因为它是等效
的.
建议弃用throw
属性,以支持@throws(Exception)
语法,因为它是等效
的.
两年后,所有类
上,默认推导@throws(Exception)
,删除并弃用
,接口虚方法和函数指针
.该错误的行为
是为了避免初始代码破坏
,并允许延迟
到更新其代码基
为止.
对调用抛的UDA
用户,可能是个重大更改
,因为应该禁止
它.
Herb Sutter的抛值
抓值
C++异常及替代
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。