编译时评估
如果我写,
enum chars = digits ~ uppercase;
字符串会在编译时连接吗?我假设会的。如果我用字符串文字或 CTFE 函数替换它,我无法测量任何显着的性能差异(即使调用它一亿次)。如果我用 const 替换 enum 确实会有所不同。有人告诉我这样写效率很低。我认为这很方便,而且我没有看到效率低下的情况。 (顺便说一句,该行位于递归调用的函数中)。
完整代码(转换为具有不同基数的数字系统)
import std.string;
string toBase(long n, int b)
in {
assert(2 <= b && b <= 35);
} body {
static string sign;
if (n < 0) {
n *= -1;
sign = "-";
}
enum chars = digits ~ uppercase;
size_t r = cast(size_t)(n % b);
if (n == r) {
return sign ~ chars[r];
}
return toBase((n - r) / b, b) ~ chars[r];
}
编辑:更新的代码,响应评论,与问题无关
string toBase(long n, int b)
in {
assert(2 <= b && b <= 35);
} body {
enum chars = digits ~ uppercase;
long r = n % b;
char c = chars[cast(size_t) abs(r)];
if (n == r) {
return (n < 0 ? "-" : "") ~ c;
}
return toBase((n - r) / b, b) ~ c;
}
If I write
enum chars = digits ~ uppercase;
will the string be concatenated at compile time? I'm assuming it will. If I replace it with a string literal or a CTFE function I can't measure any significant performance differences (even calling it a hundred million times). I do get a difference if I replace enum with const. I've been told it's inefficient to write it like this. I thought it was kind of convenient and I don't see the inefficiency. (BTW, the line is in a function that's called recursively).
The full code (converting to a numeral system with a different base)
import std.string;
string toBase(long n, int b)
in {
assert(2 <= b && b <= 35);
} body {
static string sign;
if (n < 0) {
n *= -1;
sign = "-";
}
enum chars = digits ~ uppercase;
size_t r = cast(size_t)(n % b);
if (n == r) {
return sign ~ chars[r];
}
return toBase((n - r) / b, b) ~ chars[r];
}
Edit: updated code, in response to comments, not relevant to the question
string toBase(long n, int b)
in {
assert(2 <= b && b <= 35);
} body {
enum chars = digits ~ uppercase;
long r = n % b;
char c = chars[cast(size_t) abs(r)];
if (n == r) {
return (n < 0 ? "-" : "") ~ c;
}
return toBase((n - r) / b, b) ~ c;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
像这样的
enum
实例化总是在编译时求值(并且当编译时不可能求值时抛出编译错误),因此串联是在编译时完成的,并且不可变版本存储在代码中并在运行时引用
enum
instantiations like that are always evaluated at compile-time (and throw compile errors when the evaluation is impossible at compile time)so the concatenation is done at compile-time and an immutable version is stored in the code and referenced at runtime
自行检查字符串是否在编译时连接的一种方法是编译代码并检查目标文件。假设您的文件名为
test.d
:...应该生成类似以下内容的内容:(
这是在 Linux 上;在其他平台上,您需要不同的工具来检查目标文件。)
如果您更改将
enum
转换为const
或string
,您(可能)不会得到任何输出:grep
不会有连接字符串代码> 来查找。但即使不使用
enum
,编译器也可能在编译时连接字符串。考虑这个程序:现在,编译它,并检查目标文件:
我们看到
x
、y
和z
都是静态文字。 (将a
、b
和c
标记为const
而不是enum
,并且您可能会看到不同的行为。)因此,虽然enum
是编译时评估的保证,但缺少enum
并不会阻止编译时评估。One way to check for yourself whether the string is concatenated at compile time is to compile the code and examine the object file. Assuming your file is called
test.d
:...should produce something like:
(This is on Linux; on other platforms, you'll need different tools to inspect the object file.)
If you change your
enum
toconst
orstring
, you will (probably) get no output: there will be no concatenated string forgrep
to find.But the compiler may concatenate strings at compile-time even when
enum
is not used. Consider this program:Now, compile it, and examine the object file:
We see that
x
,y
andz
are all static literals. (Marka
,b
andc
asconst
instead ofenum
, and you may see different behaviour.) So, whileenum
is a guarantee of compile-time evaluation, the absence ofenum
doesn't prevent compile-time evaluation.