digitalmars.D.learn - Inter-module symbol resolution error of template type-parameter when
- =?UTF-8?B?Tm9yZGzDtnc=?= (124/124) Sep 27 2017 At
- =?UTF-8?B?Tm9yZGzDtnc=?= (16/17) Sep 28 2017 Thanks Adam for your advice at
At https://github.com/nordlow/phobos-next/blob/03b4736fdd65ef84c6fc583eddee4196629cea81/src/variant_arrays.d I've implemented a lightweight-polymorphic array container I call `VariantArrays(Types...)` indexed by a corresponding polymorphic index I call `VariantIndex(Types...)`. It uses `.mangleof` together with mixins to automatically infer the definition (including its name) of each array store for each element type in `Types`. The element types are passed in the template parameter `Types` to the two templated structs mentioned above. Everything works except for when I try to instantiate `VariantArrays` from within a module other than `variant_arrays.d`. For instance, if I try to use it another module containing unittest { struct S { int x; } import variant_arrays : VariantArrays; VariantArrays!S a; } I get the error variant_arrays.d-mixin-130(130,1): Error: undefined identifier `S` foo.d(5,5): Error: template instance variant_arrays.VariantArrays!(S) error instantiating In other words, the symbol `S` cannot be resolved in the scope of `VariantArrays` eventhough it's feed as a template parameter. Is there a way around this problem? Here follows the definition of variant_arrays.d (excluding unittests): /** 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; }()); }
Sep 27 2017
On Wednesday, 27 September 2017 at 18:24:04 UTC, Nordlöw wrote:At ...Thanks Adam for your advice at https://stackoverflow.com/questions/46454887/inter-module-symbol-resolution-error-of-template-type-parameter-when-using-mixin?noredirect=1#comment79867792_46454887 I made things work in this version https://github.com/nordlow/phobos-next/blob/ef7e4fd59725400b4f1552f1f21cef050550a8a4/src/variant_arrays.d by using private static immutable(string) arrayTypeStringOfIndex(uint typeIndex)() { return `CopyableArray!(Types[` ~ typeIndex.stringof ~ `])`; } instead of the previous private static immutable(string) arrayTypeString(Type)() { return `CopyableArray!(` ~ Type.stringof ~ `)`; }
Sep 28 2017