My template tuple code does not compile

Simen Kjærås simen.kjaras at gmail.com
Fri Mar 1 10:12:28 UTC 2019


On Wednesday, 27 February 2019 at 22:45:03 UTC, Victor Porton 
wrote:
> I rewrote it again:
>
> https://github.com/vporton/struct-params-dlang/blob/f50f7e5919f90b1d06bf0cc08e3055548aad1797/source/struct_params.d
>
> But it does not work :-( What is my error?
>
> source/struct_params.d(43,60): Error: function expected before 
> `()`, not `()` of type `()`
> source/struct_params.d(44,43): Error: undefined identifier 
> `fieldsWithDefaults`
> source/struct_params.d(56,11): Error: template instance 
> `struct_params.ProviderParamsCode!("S", int, "x", float, "y")` 
> error instantiating
> source/struct_params.d(82,5): Error: mixin 
> `struct_params.__unittest_L81_C1.ProviderParams!("S", int, "x", 
> float, "y")` error instantiating

You seem to have misunderstood how staticMap works. It operates 
on a compile-time list of values, and only takes a single set of 
parameters: staticMap!(fn, item0, item1, item...), not 
staticMap!fn(item0, item1, item...).

In addition, Types.length.iota will create a run-time range of 
values, not a compile-time AliasSeq of values. For this, you can 
use std.meta.aliasSeqOf: staticMap!(regularField, 
aliasSeqOf!(Types.length.iota)).

Next, join expects a range, not an AliasSeq. In other words, 
staticMap!(...).join('\n') will fail to compile - staticMap!(...) 
will need to be turned into a range of some sort. We can do this 
the same way we'd turn any list of values into a range - by 
putting brackets around it. Just like [1,2,3] is a valid array, 
so is [staticMap!(...)], supposing the elements have some common 
type.

But wait - there's more! You're using __traits(identifier, 
Types[i]). As pointed out in 
https://forum.dlang.org/post/smgsgycpgvtagfsdxapi@forum.dlang.org, this will fail for built-in types, as they don't have an identifier. You can get their names, as well as the name of any other type with Types[i].stringof.

Lastly, you have not imported std.typecons, so your use of 
Nullable will fail.

So, that's the issues that cause it to not compile. There are 
issues also in the code that isn't instantiated, i.e. 
callFunctionWithParamsStruct and 
callMemberFunctionWithParamsStruct. Since these aren't used, they 
don't cause compile failure yet. The main issue here is exactly 
the same as above: a conflation of run-time and compile-time 
responsibilities, this time when using map.

Since map is a run-time function, it can't do compile-time things 
like __traits(getMember) - you'll need to use staticMap for that. 
However, there's a much easier solution:

auto callFunctionWithParamsStruct(alias f, S)(S s) {
     return f(s.tupleof);
}

The same thing can be done for callMemberFunctionWithParamsStruct.

Now, I will note that no checking is done that parameter names 
and field names match, so void fun(int numberOfBeans, string 
nameOfCat) can easily be called with struct S { int 
temperatureOfPudding; string declarationOfIndependence; }, but I 
will assume that's because you haven't gotten around to it yet.

--
   Simen


More information about the Digitalmars-d-learn mailing list