static assert not printing out along the error diagnostic
jfondren
julian.fondren at gmail.com
Wed Jul 14 06:28:37 UTC 2021
On Wednesday, 14 July 2021 at 03:06:06 UTC, someone wrote:
> in main() ... so then I went to the D docs and to Ali's book
> afterward and there I tested his example to same results.
The current behavior seems like it could be taken for a bug, or
at least room for improvement in letting static assertions fail
faster than other template instantiation, but the workaround
seems to be to require all branches of a static if to be valid
from the perspective of the rest of the code. Which is very easy
to do if you just don't have these branches at all.
case 1:
```d
public struct gudtUGC(typeStringUTF) {
static if (! (is (typeStringUTF == string) || is
(typeStringUTF == wstring) || is (typeStringUTF == dstring))) {
static assert(false, r"ooops … gudtUGC structure requires
[string|wstring|dstring] ≠ ["d ~ typeStringUTF.stringof ~ r"]"d);
} else {
// actual structure code
}
}
```
alternate 1:
- pull tests out into a named enum template, like std.traits
- always static assert enum, rather than conditionally asserting
false
- always have the rest of the code
```d
enum isString(T) = is(T == string) || is(T == wstring) || is(T ==
dstring);
// very similar to std.traits.isSomeString
struct gudtUGC(T) {
static assert(isString!T, "error message");
// unconditional structure code
}
```
case 2:
```d
struct MyType(T) {
static if (is (T == float)) {
alias ResultType = double;
} else static if (is (T == double)) {
alias ResultType = real;
} else {
static assert(false, T.stringof ~ " is not supported");
}
// code relying on some ResultType
}
```
alternate 2a:
- create a type function with std.meta
```d
enum SmallFloat(T) = is(T == float) || is(T == double);
template largerFloat(T) {
import std.meta : AliasSeq, staticIndexOf;
static assert(SmallFloat!T, T.stringof ~ " is not supported");
alias largerFloat = AliasSeq!(void, double,
real)[1+staticIndexOf!(T, AliasSeq!(float, double))];
}
struct MyType(T) {
alias ResultType = largerFloat!T;
// code relying on some ResultType
}
```
alternate 2b:
- at least make all the branches valid
```d
enum SmallFloat(T) = is(T == float) || is(T == double);
struct MyType(T) {
static assert(SmallFloat!T, T.stringof ~ " is not supported");
static if (is(T == float)) {
alias ResultType = double;
} else static if (is(T == double)) {
alias ResultType = real;
} else {
alias ResultType = void; // dummy
}
// code relying on ResultType
}
```
A benefit of having tests like SmallFloat is that you can use
them with template constraints...
```d
void moreWork(T)() if (SmallFloat!T) { }
unittest {
moreWork!float; // this is fine
moreWork!real; // !
}
```
... and get readable error messages out of the box, without
having to write static assert messages:
```
example.d(23): Error: template instance `example.moreWork!real`
does not match template declaration `moreWork(T)()`
with `T = real`
must satisfy the following constraint:
` SmallFloat!T`
```
More information about the Digitalmars-d-learn
mailing list