【发布时间】:2012-01-27 06:26:29
【问题描述】:
我在学D,见过很多这样的代码:
ushort x = to!ushort(args[1]);
我假设这会将args[1] 转换为ushort,但这与cast(ushort) 有什么区别?
编辑:感叹号运算符还有什么其他用途?
【问题讨论】:
我在学D,见过很多这样的代码:
ushort x = to!ushort(args[1]);
我假设这会将args[1] 转换为ushort,但这与cast(ushort) 有什么区别?
编辑:感叹号运算符还有什么其他用途?
【问题讨论】:
在 D 中,
to!ushort(args[1])
是模板实例化
的简写to!(ushort)(args[1])
和类似
to<ushort>(args[1])
在 C++/Java/C# 等语言中。
感叹号是要注意它不是常规参数,而是模板参数。
符号确实不使用尖括号,因为它们对于编译器来说可笑很难正确解析(它们使语法对上下文非常敏感),这使得它实现正确的编译器要困难得多。请参阅here 了解更多信息。
我知道的唯一其他用途只是一元“非”操作(例如false == !true)...我暂时想不出其他用途。
关于演员:
cast(ushort) 是一个 unchecked 强制转换,因此如果值超出范围,它不会抛出异常。
to!ushort() 是一个 checked 强制转换,因此如果值超出范围,它会引发异常。
【讨论】:
to!ushort(val) 实际上并不是演员表。这是使用函数std.conv.to 进行的转换。它被选中,但如果你开始称它为演员表,你就有可能引起混淆。只能使用 cast 操作符进行转换。
std.conv.to 所做的不仅仅是在执行转换之前检查转换是否有效。它通常处理转换。 std.conv.to是通用的转换函数,非常灵活。
这里的感叹号不是运算符,它只是显式模板实例化语法的一个记号部分(详细描述here)。
std.conv.to (docs) 是一个用于任意类型之间转换的函数模板。它完全在库中实现,语言没有特殊支持。与强制转换运算符相比,它具有更广泛和不同的范围。
to 模板有两个类型参数; “to”类型和“from”类型,按此顺序。在您的示例中,模板使用“to”参数的单个类型参数ushort 显式实例化,并且自动推断出第二个类型参数string(假设args 来自main 的第一个参数)从作为“from”参数传递给函数 (args[1]) 的常规函数参数。
生成的函数接受一个字符串参数并返回从该字符串解析的 ushort,如果失败则抛出异常。强制转换运算符不会尝试这种高级别的转换。
请注意,如果有多个显式模板参数,或者该参数中有多个标记(ushort 是单个关键字标记),则必须将模板参数列表括在括号中:
ushort result;
result = to!(typeof(result))(args[1]);
在本例中,typeof、(、result 和 ) 是四个单独的标记,因此需要括号。
为了回答您的最后一个问题,! 标记也用于一元非运算符,与模板实例化无关:
bool yes = true;
bool no = !yes; // 'no' is false
【讨论】:
你已经得到了 jA_cOp 和 Merhdad 的两个很好的答案。我只想直接回答 OP 问题(这和 cast(ushort) 有什么区别?) - 区别在于 cast(ushort)args[1] 不起作用(你不能从字符串转换为 uint就像那样),而to!(type)(param) 模板知道如何处理字符串以及如何将其转换为原始类型。
【讨论】: