首页 > 解决方案 > 为什么 DMD 无法编译以下 D 代码片段?

问题描述

我正在学习 D 并使用run.dlang.io进行调试。下面的代码在run.dlang.io上运行没有问题:

import std.stdio;
import std.algorithm;
import std.range;
import std.typecons;

static bool even(Tuple!(ulong, double) a) {
    return (a[0] & 1) == 0;   
}

void main() {
    double[] arr = [31, 22, -3, 44, 51, 26, 47, 58, 19, 10];  
    auto res1 = arr.enumerate.filter!(even).map!(a => a[1]);
    writeln(res1);    
}

dmd temp.d但是,DMD32 v2.088在 Windows 10 上编译完全相同的代码时会引发异常。

Error: function temp.even(Tuple!(ulong, double) a) is not callable using argument types (Tuple!(uint, "index", double, "value")) 

而 LDC 编译器 (1.18.0-beta1): (基于 DMD v2.088.0 和 LLVM 8.0.1) 编译相同的文件没有问题。

run.dlang.io使用 2.087 dmd 编译器,它以某种方式神奇地工作,为什么它不能在 Windows 上工作?

标签: d

解决方案


在 Windows 上,您的应用程序默认为 32 位构建。在 OSX 和 Linux(这是 run.dlang.io 正在运行的)上,它默认为 64 位构建。

因此,数组索引分别为 uint 和 ulong。在您使用的代码中Tuple!(ulong, double),但在 32 位上,它使用 uint 索引调用。

您应该使用size_t映射到 uint/ulong 的索引,而不是使用 ulong/uint。这是在object.d中定义的,默认情况下包含在内。

因此,如果您将功能更改为

static bool even(Tuple!(size_t, double) a) {
    return (a[0] & 1) == 0;   
}

它将在 32 位和 64 位上运行。

在 Windows 上,您还可以使用 dub 测试您的代码,方法是使用--arch=x86_64或使用 dmd 标志运行它-m64,它应该已经可以在没有更改的情况下工作。我建议始终在 32 位和 64 位上测试您的应用程序,以确保您size_t在需要的地方使用。


推荐阅读