Межмодульная ошибка разрешения символа типа-параметра шаблона при использовании mixins

В

https://github.com/nordlow/phobos-next/blob/03b4736fdd65ef84c6fc583eddee4196629cea81/src/variant_arrays.d

Я реализовал легкий массив полиморфных массивов, который я называю 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;
        }());
}

0 ответов

Другие вопросы по тегам