可这样:

static assert(float() is float.nan);

这仅适合​​float.init​​​,但如果操作它并返回​​nan​​​,那不一定是真的,因为​​nans​​​有几种​​位模式​​.

static assert(float() is real.nan);
static assert(double() is real.nan);
static assert(real() is real.nan);

同小类型比较,会提升.
除了​​​T.nan​​​还有其他类型​​NaN​​​吗?如何生成它们?
​​​0F/0F is float.nan​​​是真.
与​​​大小​​​无关,而是​​nan​​们可以不同形式出现.考虑:

void main() {
float f = 7.0;
f /= 0;
import core.stdc.stdio;
printf("%d\n", *cast(int*)&f);
if(f is float.init)
printf("nan\n");
}

该与​​float.init​​不一样,

f = 1.0;
f /= 0;
assert(f is f.infinity);
//
float f = 0;
f /= 0;
assert(f is f.nan); //失败了.

这样来零初化:

template ZeroInit(T)
{
union U
{
byte[T.sizeof] a;
T zeroed;
}
enum ZeroInit = U().zeroed;
}

struct S
{
float f;
float[2] a;
}

void main()
{
S s = ZeroInit!S;
assert(s.f == 0);
assert(s.a == [0,0]);
}

​int.min​​​并不是真正的​​NaN​​​.
但它应该是!​​​int.min​​​是臭名昭著的​​虚假值​​​.甚至不能在它上面使用​​abs()​​​:它要么给你不同类型,要么​​返回垃圾​​​.
我在​​​每个程序​​​中做的第一件事就是​​精确​​​定义:​​byte/short/int/long​​​的别名,置​​T.min+1​​​为实际​​最小值​​​.
不必自己写;可用​​​std.checkedint​​​的​​Checked!(int,WithNaN)​​​,​​在此​

可以这样,用​​std.typecons.Typefef​​:

import std;

alias Distance = Typedef!(double, 0.0, "distance");
alias Temperature = Typedef!(double, 0.0, "temperature");

void main()
{
Temperature t;
Distance d;
d += 4.5;
// t = d; // 不编译
}

但是,可能会在​​中间结果​​​中丢失​​类型信息​​:

t = 0.5 + d;//结果为双精

包含​​NaN​​​和​​无穷大​​​等值理由:重点是​​简化​​​错误处理,并允许​​延迟​​处理错误.

​alias this​​是隐式转换工具.

个人喜欢D的做法.一旦你知道​​浮点​​​有个​​"无"​​​的​​方便初化值​​​,同样原因​​null​​​是​​指针和类引用​​​的方便初化值.但如果我不知道​​NaN​​​,这会很烦人.最大​​弱点​​​是它违背了​​C,C++​​​和​​C#​​​(等其他语言)做法,很容易让人感到​​惊讶​​​.
背后​​​重要理念​​​是D总是用​​"空"值​​​作为​​初化值​​​(如果有的话).
另一方面,程序员可​​​显式初化​​​变量为​​float.nan​​​.
我在​​​每个程序​​​中都包含它,且从不使用其他​​有符号​​​整数(​​正值​​​用于​​位操作​​​,而不是计算).​​checkedint​​​应只是​​int​​​类型,而不是​​模块​​.