constructing labels for static foreach inside switch inside foreach
cc
cc at nevernet.com
Wed Jul 8 09:10:49 UTC 2020
On Wednesday, 8 July 2020 at 02:06:01 UTC, Steven Schveighoffer
wrote:
> OK, so I have a situation where I'm foreaching over a
> compile-time list of types. Inside the loop, I'm using a second
> loop over a set of input.
>
> Inside that loop, I'm using a switch on the input, and inside
> the switch, I'm foreaching over the type's members, to
> construct a switch that can handle member names (this is for
> serialization).
>
> If I encounter a certain name, then I want to break out of the
> inner loop (it's a while loop)
>
> So naturally, I have to use break statements with labels like:
>
> innerloop:
> while(haveMoreData)
> switchstmt:
> switch(nextDataElement) {
> static foreach(name; __traits(allMembers, T)) {
> case name:
> ... // handle it
> break switchstmt;
> }
> case "STOP":
> break innerloop;
> }
>
> Seems simple enough, except that this inner portion is
> unrolled, and if I have more than one type to run this on, I
> already have an "innerloop" label defined.
>
> Is there a way to define a label using a mixin or something? or
> do I have to wrap this in a function?
>
> Is there another way to approach this?
>
> -Steve
I think I ran into similar problems due to the requirement to use
a labeled break inside static foreach. I got around it by
defining enums when my target was found and checking if it
existed via __traits(compiles) to "ignore" the rest of the loop.
Sorry if I got what you're trying to accomplish wrong or this is
too ugly:
class Foo {
@(RPC) bar(int x, float f, string s) {
// ...
}
}
class Remoter(T) {
void opDispatch(string s, SA...)(SA sargs) {
alias A = getSymbolsByUDA!(T, RPC);
static foreach (idx, FUNC; A) {
static if (!__traits(compiles, FOUND) && hasUDA!(FUNC, RPC) &&
FUNCNAME!FUNC == s && SA.length == (Parameters!FUNC).length) {
version(CheckImplicitlyConvertibleArgs) {
static foreach (argi; 0 .. SA.length) {
static if (!__traits(compiles, mixin(format("MISMATCH_%d",
idx)))) {
static if (isImplicitlyConvertible!(SA[argi],
(Parameters!FUNC)[argi])) {
//pragma(msg, format("implc ok: %s => %s",
SA[argi].stringof, (Parameters!FUNC)[argi].stringof));
// Parameter Ok
} else {
pragma(msg, format("RPC argument[%s] of %s is not
implicitly convertible: %s => %s", argi, FUNCNAME!FUNC,
SA[argi].stringof, (Parameters!FUNC)[argi].stringof));
mixin(`enum bool `~format("MISMATCH_%d", idx)~` = true;`);
}
}
}
static if (!__traits(compiles, mixin(format("MISMATCH_%d",
idx)))) {
enum FOUND = idx;
//pragma(msg, format("and we found: %s", FOUND));
}
} else {
enum FOUND = idx;
}
}
}
static if (__traits(compiles, FOUND)) {
alias FUNC = A[FOUND];
// generate a packet to transmit that corresponds to RPC
function call
} else {
static assert(0, format("No matching function found for %s%s",
s, SA.stringof));
}
}
}
Remoter!foo remote;
remote.bar(4, 3.14f, "hello"); // succeeds
remote.bar("hi", 12); // static assert fail
More information about the Digitalmars-d-learn
mailing list