static assert not printing out along the error diagnostic
someone
someone at somewhere.com
Thu Jul 15 01:16:10 UTC 2021
On Wednesday, 14 July 2021 at 23:44:18 UTC, jfondren wrote:
> On Wednesday, 14 July 2021 at 22:59:38 UTC, someone wrote:
>> [...]
>
> so, these lines:
>
> ```d
> stringUGC32 lugcSequence3 = stringUGC32(cast(char) 'x');
> stringUGC32 lugcSequence4 = stringUGC32(1);
> ```
>
> which call stringUGC32, an alias:
>
> ```d
> alias stringUGC32 = gudtUGC!(stringUTF32);
> alias stringUTF32 = dstring; /// same as immutable(dchar)[];
> ```
>
> which explicitly instantiates gudtUGC with the type dstring,
>
> ```d
> enum isTypeSupported(type) = is(type == stringUTF08) || is(type
> == stringUTF16)
> || is(type == stringUTF32);
> ...
> public struct gudtUGC(typeStringUTF) {
> static assert(isTypeSupported!(typeStringUTF),
> r"ooops … gudtUGC structure requires
> [string|wstring|dstring] ≠ ["d
> ~ typeStringUTF.stringof ~ r"]"d);
> ```
>
> which passes the assert.
>
> You're explicitly instantiating the struct with dstring, *not
> getting an assertion error because dstring passes the test*,
> and are then passing the constructor a different type, which
> gets you a type error at that time.
I can't believe I completely forgot about my alias; I am a stupid
to the say the least, I raised this issue without thinking much :(
> However, even if you avoid that alias and try either implicit
> or explicit instantiation of the template with bad types, the
> template instantiation fails first in random other places, like
> a default param of " " not making sense as a char:
>
> ```d
> staticif1.d(369): Error: cannot implicitly convert expression
> `" "` of type `string` to `const(char)`
> staticif1.d(387): Error: cannot implicitly convert expression
> `" "` of type `string` to `const(char)`
> staticif1.d(545): Error: template instance
> `fw.types.UniCode.gudtUGC!char` error instantiating
> ```
>
> So, yeah, even with no static ifs in the file, you're still not
> getting these static asserts to fail before other parts of the
> template. Conclusion: you shouldn't rely on static asserts
> providing a good UI in the case of an error. They still *work*,
> the struct still wouldn't instantiate with a `char` or the like
> if all the other char-incompatibilities were removed, but for
> UI purposes they're not great because you can't rely on them
> firing according to normal control flow.
ACK for the static asserts.
> You're using aliases though, and not instantiating the struct
> directly. If you make those function templates you can use
> template constraints with them, which does result in a nice UI:
A few days ago when I started coding this UDT (and started
thinking of *actually using it*) the first thing that came to
mind was that to get a simple, say, strWhatever.left(1) I would
end up writing gudtUGC!(dstring)(strWhatever).left(1).encode() or
gudtUGC!(dstring)(strWhatever).leftAsUTF(1) or something akin to
these ones, so I played a bit with the aliases and ended up with
gudtUGC[08|16|32] which seemed a bit more friendly and
crystal-clear on their types. The thing with aliases is that they
are really useful *until* you forgot you're using aliases and end
up biting yourself on a situation like this one. Again, sorry for
being too silly on my part.
> ```d
> gudtUGC!stringUTF08 thing8(T)(T arg) if (isTypeSupported!T) {
> return gudtUGC!T(arg); }
> gudtUGC!stringUTF16 thing16(T)(T arg) if (isTypeSupported!T) {
> return gudtUGC!T(arg); }
> gudtUGC!stringUTF32 thing32(T)(T arg) if (isTypeSupported!T) {
> return gudtUGC!T(arg); }
>
> ...
>
> stringUGC32 lugcSequence3 = thing32(cast(char) 'x');
> stringUGC32 lugcSequence4 = thing32(1);
> ```
>
> (introducing new 'thing' functions as stringUGC32 used is
> elsewhere as a type and not just a function. So you still need
> the aliases.)
>
> Which fails in this manner:
>
> ```d
> staticif1.d(548): Error: template `fw.types.UniCode.thing32`
> cannot deduce function from argument types `!()(char)`,
> candidates are:
> staticif1.d(46): `thing32(T)(T arg)`
> with `T = char`
> must satisfy the following constraint:
> ` isTypeSupported!T`
> ```
>
> and would fail more verbosely if the three functions had the
> same name, instead of numbered names to follow the stringUGC32
> pattern.
>
> `isTypeSupported` isn't great here, but you can pick a more
> precise name. Or in the case of already numbered functions like
> this, you could use more precise tests... or just drop the
> tests entirely and have non-templated functions:
>
> ```d
> gudtUGC!stringUTF08 thing8(stringUTF08 arg) { return
> typeof(return)(arg); }
> gudtUGC!stringUTF16 thing16(stringUTF16 arg) { return
> typeof(return)(arg); }
> gudtUGC!stringUTF32 thing32(stringUTF32 arg) { return
> typeof(return)(arg); }
> ```
>
> which results in normal type errors:
>
> ```
> staticif2.d(548): Error: function
> `fw.types.UniCode.thing32(dstring arg)` is not callable using
> argument types `(char)`
> staticif2.d(548): cannot pass argument `'x'` of type
> `char` to parameter `dstring arg`
> ```
I will explore this approach.
Thank you very much for your time and your detailed step-by-step
reply. I guess you were LoL when you first saw this one :) !
More information about the Digitalmars-d-learn
mailing list