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/smgsgycpgvtagfsdx...@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