I was playing around with alias this
which can simulate inheritance for structs in D. For a library that I recently started I also would like to provide trait templates which detect the proper type via is
-expression.
Here is my type hierarchy.
struct R(X) {
S!X s;
alias s this;
this(X i) { s = i; }
}
struct S(X) {
T a;
alias T = X;
alias a this;
this(T t) { a = t; }
}
import std.stdio : writeln;
void main()
{
R!int r = 3;
S!int s = r;
int i = r;
writeln(r, " ", s, " ", i );
static assert( is(r.s.T) && is(typeof(r) : S!(r.s.T)) );
static assert( is(typeof(r) : R!X, X) );
static assert( is(typeof(r) : int) && is(typeof(r) : S!int) );
alias T = int;
static assert( is(typeof(r) : S!T) );
static assert(
is(typeof(r) : S!Q, int Q) ||
is(typeof(r) : S!Q, Q) ||
is(typeof(r) : S!Q, r.s.T Q) ||
is(typeof(r) : R!Q, int Q) ||
is(typeof(r) : R!Q, r.s.T Q)
);
}
I would expect all the static asserts
to be true, so it is able to match a generic template argument via template specialization. But in reality, the last static assert
is false
! This is not just rdmd
or dmd
but also ldc2
. I suppose, I made something wrong here.
My question is, how to extract the generic template argument X
from type S!X
properly without using an alias r.s.T
from my example? I'd like to do that via is
-expression.
This question is specifically about struct
. For performance and proramming experience, I will not use class inheritance instead of alias this
. My struct will only be a small wrapper around a member field whose main purpose is overloading of some operators.
Thank you.
You need to use is
INSIDE static if
to do the extraction.
static if(is(typeof(r) == R!Q, Q))
pragma(msg, Q); // will print that int, you can just use Q as a type inside this branch
else
// not an instance of R
is(typeof(r) : R!Q, r.s.T Q) means the type of r implicitly casts to R!Q where Q is a value of type int. So that would be like R!4 or something. Same with the previous two and the first lines, they are looking for Q to be a value, not a type. Only the second item there is in the correct form to match this at all.... and I would guess it doesn't just because the compiler isn't smart enough to look that deep into it. Like a lot of is exprs realistically work best with one level of ask - implicit convert OR extract args. Here it asks to do both and tbh prolly a compiler bug / lazy impl.