编译时foreach在函数体外部

时间:2016-05-28 13:25:27

标签: foreach d compile-time

有没有办法让exach在函数体外面为ex。生成代码。

我的场景是我在编译时有一个关联数组,我需要用它来生成特定的字段。不幸的是,我无法在函数体外部使用foreach来生成成员。

现在我正在使用一个解决方法,我有一些mixin,我给第一个mixin一个AA,mixin将AA转换为数组并将其传递给第二个mixin,第二个mixin是递归的本身由ng本身直到没有更多的成员,同时也调用数组中的第一个成员,它调用我可以用来生成代码的第三个mixin。

它不像我真正希望的那样平滑和动态,我想知道是否有人有更好的解决方案。

这是我的解决方案

// First mixin that takes the associative array and a string for the mixin to handle the items
mixin template StaticForEachAA(TKey,TValue, TKey[TValue] enumerator, string itemMixin) {    
    enum array = arrayAA!(TKey,TValue)(enumerator); // Converts the AA to an array of key-value pair structs
    alias ArrayType = KeyValuePair!(TKey,TValue);

    mixin StaticForEachArray!(ArrayType, array, itemMixin); // Calls second mixin with the array
}

// The second mixin that "fake loops" the array
mixin template StaticForEachArray(T, T[] array, string itemMixin) {
    static if (array.length) {
        import std.string : format;

        mixin(format("mixin %s!(T, array[0]);", itemMixin)); // Mixins the itemMixin to handle the current item
        mixin StaticForEachArray!(T, array[1 .. $], itemMixin); // slices the array to remove the item we just handled
    }
}

// The third mixin that can be used to do whatever has to be done with item
mixin template StaticForEachItem(T, T item) {
    import std.conv : to;
    pragma(msg, to!string(item));
}

为关联

做“假foreach”
enum AA = [0 : 1, 1 : 2, 2 : 3];

mixin StaticForEachAA!(int, int, AA, "StaticForEachItem");

这将在编译时从AA打印键值对。

1 个答案:

答案 0 :(得分:1)

利用编译时功能执行(CTFE)的强大功能,您可以创建一个辅助函数,使用您提供的关联数组(AA)中的数据为您生成代码。

import std.string : format;

string generateCodeForEachAA(TKey, TValue)(TValue[TKey] data, string foreachBody)
{
  string result;
  foreach(k, v ; data)
  {
    result ~= format(foreachBody, k, v);
  }

  return result;
}

此函数通过使用每个AA元素格式化给定的foreachBody将给定的AA数据转换为字符串。然后返回的字符串可以是mixin'ed:

enum Data = [ 0 : 1, 1 : 2, 2 : 3 ];

enum Code = generateCodeForEachAA(Data, q{ pragma(msg, "%1$s => %2$s"); });

pragma(msg, "Code: " ~ Code);

mixin(Code);

输出:

Code:  pragma(msg, "0 => 1");  pragma(msg, "1 => 2");  pragma(msg, "2 => 3");
0 => 1
1 => 2
2 => 3

使用它在结构中生成成员:

struct Foo
{
  enum Members = [ "foo": 123, "bar": 42 ];
  mixin(generateCodeForEachAA(Members, q{ typeof(%2$s) %1$s = %2$s; }));
}

void main()
{
  import std.stdio : writeln;

  Foo f;
  writeln("foo: ", f.foo);
  writeln("bar: ", f.bar);
}

输出:

foo: 123
bar: 42