在
我已经实现了一个轻量级多态数组容器,我称之为VariantArrays(Types...)
由我调用的相应多态索引索引VariantIndex(Types...)
。
它.mangleof
与 mixins 一起使用来自动推断Types
. 元素类型在模板参数中传递Types
给上面提到的两个模板结构。
一切正常,除了当我尝试VariantArrays
从variant_arrays.d
. 例如,如果我尝试在另一个包含
unittest
{
struct S { int x; }
import variant_arrays : VariantArrays;
VariantArrays!S a;
}
我得到错误
variant_arrays.d-mixin-130(130,1): Error: undefined identifier `S`
foo.d(5,5): Error: template instance variant_arrays.VariantArrays!(S) error instantiating
换句话说,即使它是作为模板参数提供的S
,也无法在范围内解析符号。VariantArrays
有没有办法解决这个问题?
也在这里发布:http: //forum.dlang.org/post/einvuqvpeoeubkwhwbbm@forum.dlang.org
以下是variant_arrays.d
(不包括单元测试)的定义:
/** Polymorphic index into an element in `VariantArrays`. */
private struct VariantIndex(Types...)
{
import std.meta : staticIndexOf;
private:
alias Kind = ubyte; // kind code
alias Size = size_t; // size type
import bit_traits : bitsNeeded;
/// Number of bits needed to represent kind.
enum kindBits = bitsNeeded!(Types.length);
/// Get number kind of kind type `SomeKind`.
enum nrOfKind(SomeKind) = staticIndexOf!(SomeKind, Types); // TODO cast to ubyte if Types.length is <= 256
/// Is `true` iff an index to a `SomeKind`-kind can be stored.
enum canReferTo(SomeKind) = nrOfKind!SomeKind >= 0;
/// Construct.
this(Kind kind, Size index) // TODO can ctor inferred by bitfields?
{
_kindNr = kind;
_index = index;
}
import std.bitmanip : bitfields;
mixin(bitfields!(Size, "_index", 8*Size.sizeof - kindBits,
Kind, "_kindNr", kindBits));
}
/** Stores set of variants.
Enables lightweight storage of polymorphic objects.
Each element is indexed by a corresponding `VariantIndex`.
*/
private struct VariantArrays(Types...)
{
alias Index = VariantIndex!Types;
import basic_copyable_array : CopyableArray;
/// Returns: array type (as a string) of `Type`.
private static immutable(string) arrayTypeString(Type)()
{
return `CopyableArray!(` ~ Type.stringof ~ `)`;
}
/// Returns: array instance (as a strinng) storing `Type`.
private static immutable(string) arrayInstanceString(Type)()
{
return `_values` ~ Type.mangleof;
}
/** Insert `value` at back.
*/
pragma(inline) // DMD cannot inline
Index insertBack(SomeKind)(SomeKind value) // TODO add array type overload
if (Index.canReferTo!SomeKind)
{
mixin(`alias arrayInstance = ` ~ arrayInstanceString!SomeKind ~ `;`);
const currentIndex = arrayInstance.length;
arrayInstance.insertBack(value);
return Index(Index.nrOfKind!SomeKind,
currentIndex);
}
alias put = insertBack; // polymorphic `OutputRange` support
/// Get reference to element of type `SomeKind` at `index`.
scope ref inout(SomeKind) at(SomeKind)(in size_t index) inout return
if (Index.canReferTo!SomeKind)
{
mixin(`return ` ~ arrayInstanceString!SomeKind ~ `[index];`);
}
/// Peek at element of type `SomeKind` at `index`.
scope inout(SomeKind)* peek(SomeKind)(in Index index) inout return @system
if (Index.canReferTo!SomeKind)
{
if (Index.nrOfKind!SomeKind == index._kindNr)
{
return &at!SomeKind(index._index);
}
else
{
return null;
}
}
private:
// TODO this fails:
mixin({
string s = "";
foreach (Type; Types)
{
s ~= arrayTypeString!Type ~ ` ` ~ arrayInstanceString!Type ~ `;`;
}
return s;
}());
}