2016-02-29 20 views
2

編譯時是否可以將Foo轉換爲ubyte[size]在編譯時可以將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 
} 

的問題是,我不能在編譯時投Branchubyte[maxSize]

回答

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的東西是微不足道的,但正確處理字段對齊可能是一個痛苦(我甚至沒有試圖這樣做在這個片段)。

相關問題