Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
D 关联数组的编译时初始化_D - Fatal编程技术网

D 关联数组的编译时初始化

D 关联数组的编译时初始化,d,D,根据D语言参考,关联数组AA可以通过以下方式初始化: immutable long[string] aa = [ "foo": 5, "bar": 10, "baz": 2000 ]; void main() { import std.stdio : writefln; writefln("(aa = %s)", aa); } 但是,该示例没有使用合理的最新DMD进行编译: $ dmd --version DMD64 D Compiler v2.083.0 Copyrig

根据D语言参考,关联数组AA可以通过以下方式初始化:

immutable long[string] aa = [
  "foo": 5,
  "bar": 10,
  "baz": 2000
];

void main()
{
  import std.stdio : writefln;
  writefln("(aa = %s)", aa);
}
但是,该示例没有使用合理的最新DMD进行编译:

$ dmd --version
DMD64 D Compiler v2.083.0
Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved written by Walter Bright
$ dmd -de -w so_003.d
so_003.d(3): Error: non-constant expression ["foo":5L, "bar":10L, "baz":2000L]
谷歌搜索似乎表明这是该语言的一个长期缺陷:

所以我知道如何用一个。然而,考虑到这个问题已经存在了大约10年,这在实践中是否变成了一个特征

事实上,这只是我实际问题的前奏:

是否可以在编译时初始化关联数组

在下面的示例中,我可以使用生成器函数初始化模块级字符串[]doubleUnits,该函数在编译时运行,并由pragmamsg证明。我可以在运行时初始化int[string]doubleUnitMap。但是如何在编译时初始化AA呢

import std.stdio : writefln;

immutable char[] units = ['a', 'b', 'c'];

immutable string[] doubleUnits = generateDoubleUnits(units);
pragma(msg, "compile time: ", doubleUnits);

string[] generateDoubleUnits(immutable char[] units)
pure
{
  import std.format : format;

  string[] buffer;
  foreach(unit; units) {
    buffer ~= format("%s%s", unit, unit);
  }

  return buffer;
}

immutable int[string] doubleUnitMap;
// pragma(msg) below triggers the following compilation error:
// Error: static variable doubleUnitMap cannot be read at compile time
//        while evaluating pragma(msg, "compile time: ", doubleUnitMap)
// pragma(msg, "compile time: ", doubleUnitMap);

shared static this() {
  doubleUnitMap = generateDoubleUnitMap(units);
}

int[string] generateDoubleUnitMap(immutable char[] units)
pure
{
  import std.format : format;

  int[string] buffer;
  foreach(unit; units) {
    string key = format("%s%s", unit, unit);
    buffer[key] = 1;
  }

  return buffer;
}

void main()
{
  writefln("(doubleUnits = %s)", doubleUnits);
  writefln("(doubleUnitMap = %s)", doubleUnitMap);
}

目前,如语言规范文档中所述,这是不可能的。我已经提交了规范中的一个变更,并注意到该功能尚未实现。它肯定是计划好的,但尚未实现…

由于编译器不知道运行时格式,因此不可能在编译时初始化内置AAs。它知道运行时接口和编译时内存布局。。。但是运行时内存布局被委托给库,因此编译器不知道如何形成它。因此出现了错误

但是,如果您要实现自己的AA类型实现,那么您可以编写CTFE代码来进行布局,然后编译器可以在编译时完成

许多年前,这是一个修复方案,用一个恰好适合编译器接口的库AA替换内置的magic实现。然后它就可以做这一切了。问题是库类型无法表达内置关联数组的所有魔力。我不记得确切的问题,但我认为这是关于常量和其他属性交互的

但也就是说,即使100%替换失败,您自己实现的90%替换也可能足够好。声明将看起来不同-MyAA!string,int而不是string[int],它的文本是不同的,尽管可能是makeMyAA[foo:10];一个helper ctfe函数,它接受一个内置的文本并将其转换为您的格式,但由于运算符重载,用法基本相同

当然,实现您自己的AA可能需要一些代码,可能不值得,但如果CT初始化是必须的,这是使其工作的方法

就我个人而言,我发现静态构造函数已经足够好了