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

Reply via email to