是否有可能在编译时将Foo转换为ubyte [size]?

时间:2016-02-29 08:16:23

标签: d

是否可以在编译时将prod_list = [] prod1 = Product(3, 3, 3) prod_list.append(prod1) prod2 = Product(3, 3, 2) prod_list.append(prod2) prod3 = Product(3, 3, 3) print prod3 in prod_list True prod3 = Product(3, 3, 5) print prod3 in prod_list False 强制转换为Foo

以下是更多背景信息:

ubyte[size]

问题是我无法在编译时将struct Algebraic(Types...) if(Types.length < char.max - 1){ import std.traits: Largest; import std.meta: IndexOf; static immutable maxSize = Largest!(Types).sizeof; this(T)(in T t) if(IndexOf!(T, Types) !is -1){ type = IndexOf!(T, Types); data = *cast(ubyte[maxSize]*)&t; } void opAssign(T)(in T t) if(IndexOf!(T, Types) !is -1){ type = IndexOf!(T, Types); data = *cast(ubyte[maxSize]*)&t; } inout(T*) peek(T)() inout{ if(type is IndexOf!(T, Types)){ return cast(inout(T*))&data; } return null; } private: ubyte[maxSize] data; char type = char.max; } struct Branch{ int index; int left; int right; } struct Leaf{ int index; } struct Foo{ alias Node = Algebraic!(Branch, Leaf); Node n = Branch(1,2,3); //Error: cannot convert &const(Branch) to ubyte[12]* at compile time } 强制转换为Branch

1 个答案:

答案 0 :(得分:4)

我不知道任何“干净”的方法(利用ABI的编译器知识),因为CTFE在防止重新解释方面非常保守。但是,如果这是一个阻塞程序,可以手动构建字节数组,使用结构ABI非常简单:

import std.traits;

ubyte[T.sizeof] reinterpret (T) ( T x )
    if (!hasIndirections!T)
{
    typeof(return) result;

    static if (is(T == struct))
    {
        size_t offset = 0;
        foreach (ref field; x.tupleof)
        {
            result[offset .. offset + field.sizeof] = reinterpret(field);
            offset += field.sizeof;
        }
    }
    else static if (is(T : ulong))
    {
        for (auto i = 0; i < x.sizeof; ++i)
            result[i] = cast(ubyte) (x >> 8*i);
    }
    else
    {
        // handle floating types, arrays etc.
    }

    return result;
}

struct S
{
    int x, y;
}

static immutable bytes = reinterpret(S(42, 42));

pragma(msg, bytes);

此方法存在一个巨大的限制:您需要手动调整到适当的ABI。像endianess这样的东西是微不足道的,但正确处理字段对齐可能是一种痛苦(我甚至不想在这个代码片段中这样做)。