Template with template?

Chris wendlec at tcd.ie
Thu Mar 20 12:38:24 PDT 2014


On Thursday, 20 March 2014 at 18:54:30 UTC, John Colvin wrote:
> On Thursday, 20 March 2014 at 18:39:32 UTC, Chris wrote:
>> On Thursday, 20 March 2014 at 17:49:52 UTC, John Colvin wrote:
>>> On Thursday, 20 March 2014 at 16:40:50 UTC, Chris wrote:
>>>> On Thursday, 20 March 2014 at 16:32:34 UTC, Vladimir 
>>>> Panteleev wrote:
>>>>> On Thursday, 20 March 2014 at 16:28:46 UTC, Chris wrote:
>>>>>> How can I instantiate Person with Trait, i.e. a template 
>>>>>> with a template?
>>>>>>
>>>>>> struct Trait(T0, T1) {
>>>>>> T0 name;
>>>>>> T1 value;
>>>>>> T1[T0] map;
>>>>>>
>>>>>> this(T0 name, T1 value) {
>>>>>> this.name = name;
>>>>>> this.value = value;
>>>>>> map[name] = value;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> class Person(T) {
>>>>>> T traits[];
>>>>>>
>>>>>> void addTrait(T trait) {
>>>>>> traits ~= trait;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>>
>>>>>> void main()
>>>>>> {
>>>>>> auto trait1 = Trait!(string, string)("Name", "John");
>>>>>> auto trait2 = Trait!(string, int)("Age", 42);
>>>>>> writefln(%s", trait1.map);
>>>>>> writefln(%s", trait2.map);
>>>>>> // above code compiles and works
>>>>>> }
>>>>>
>>>>> Person!(Trait!(string, string)) person;
>>>>>
>>>>> -- or --
>>>>>
>>>>> alias MyTrait = Trait!(string, string);
>>>>> Person!MyTrait person;
>>>>>
>>>>> Note that this approach won't let you have traits with 
>>>>> different parameters within the same Person type.
>>>>
>>>> Yep, I've already tried this (sorry I should've mentioned 
>>>> it!). But I don't want this restriction.
>>>
>>> Arrays are homogeneous. All the elements must be of the same 
>>> type. Different instantiations of templates are different 
>>> types.
>>>
>>> You could use an array of std.variant.Variant
>>
>> The elements are all of type Trait. However, Type itself might 
>> be
>> of different types. That's why it is not possible? I've come
>> across this restriction before when using templates, which is a
>> big disappointment because it restricts the "templatization" /
>> generalization of data structures somewhat.
>
> Trait is not a type. Trait is a template. An instantiation of 
> the Trait template is a type.
>
>
> Arrays are contiguous, homogeneous data. This is fundamental to 
> their design and their performance characteristics.
> Workarounds use at least one of the following: indirection, 
> tagging* and padding. Variant uses tagging and padding. 
> Interface/base-class arrays use indirection (and tagging, 
> ultimately).
>
> *inline or external, or even compile-time.
>
> This is true in *every* programming language, just with 
> different names.

I thought the array T[] traits could hold any _type_ the template 
Trait is instantiated into. That's where I got it wrong. I 
understand the practical aspects of this restriction (homogeneous 
data, performance and the work around involved etc.). However, 
this makes templates less universal and rather cumbersome to work 
with in certain circumstances. Take for example the Person class. 
If I want to do numerical operations with the age of the person, 
I will have to convert the age to an int (or whatever) later on 
instead of just doing it once at the beginning (when loading 
data). So everytime I access Trait.map["age"] I will have to 
convert it to a number before I can calculate anything. This, or 
I store it in a field of its own when instantiating Trait. 
Whatever workaround I choose it will make it less elegant and 
less simple.

Maybe I expect(ed) to much of templates. Mea culpa.


More information about the Digitalmars-d-learn mailing list