Question about generation of template functions

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Aug 28 21:13:07 UTC 2019


On Wednesday, August 28, 2019 2:56:25 PM MDT Machine Code via Digitalmars-d-
learn wrote:
> I was writing a recursive function that uses template, I thought
> it would generate the proper template function on the fly to
> match the type in the parameter but it seems to not so so and try
>
> to use the called function, resulting in the error:
> > Error: function foo.serialize!(B).serialize(ref B output) is
> > not callable using argument types (A)
> >
> >        cannot pass argument output of type A to parameter ref B
> >
> > output
> > Error: template instance `foo.serialize!(A)` error instantiating
>
> Code:
>
> void main()
> {
>   A a = A();
>   serialize(a);
> }
>
> struct Attr {
>   string value;
>   alias value this;
> }
>
>
> struct A {
>   @(Attr("foo"))
>   int n = 10;
>   @(Attr("baa"))
>   int k = 30;
>   B b = new B();
> }
>
> class B {
>   @(Attr("hello"))
>   int pl = 10;
> }
>
> void serialize(T)(ref T output)
> {
>   import std.traits : hasUDA, getUDAs, isAggregateType;
>   import std.meta : Alias;
>
>   foreach(fieldName; __traits(derivedMembers, T))
>   {
>       alias field = Alias!(__traits(getMember, T, fieldName));
>       static if(isAggregateType!(typeof(field)))
>       {
>           serialize!(typeof(field))(output);
>       }
>       static if(hasUDA!(field, Attr))
>       {
>           enum className = getUDAs!(field, Attr)[0];
>           writefln("className = [%s]", className);
>       }
>   }
> }

If a parameter is ref, then the type of the argument must be exactly the
same type as the parameter. When you call serialize in main, it infers T to
be A, becaues you passed it an A. Within serialize, you call serialize and
explicitly instantiate it. So, T is then whatever the type is that you
provided (which in this case would be typeof(field), whatever that is for
each iteration of the compile-time foreach). If typeof(field) is ever not an
A, then you can't pass the variable output to it, because output is an A.
You need to pass it an lvalue that has the type typeof(field). I'm guessing
that you meant to pass the member variables of output to serialize one by
one and not output over and over again.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list