On Fri, 30 Mar 2012 15:03:49 +0200, simendsjo <[email protected]> wrote:
On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kjærås
<[email protected]> wrote:
On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <[email protected]>
wrote:
If you look at the struct, it uses the type U in, among others, the
union.
The only place I could see U referenced is in the first static if, but
I cannot recreate this behavior:
void main() {
static if(is(int X == const(U), U))
Ah, the magic of isExpressions...
What happens here is the isExpression asks 'if X is an int, does it
match the pattern const(U), where U is some type?'
Of course, there is no U for which const(U) == int, so the isExpresion
returns false, and your static assert triggers.
static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))
Again, 'is there a U such that const(U) == T?', then the same for
immutable(U). In other words - 'is T mutable?'.
The reason the U is there is to explain to the compiler that we're
talking about this specific U, not some other U that may be defined
elsewhere in the program.
The same pattern is used in std.typecons.isTuple:
template isTuple(T)
{
static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
{
enum isTuple = true;
}
else
{
enum isTuple = false;
}
}
It can also be extended to other templates:
struct Foo() {}
struct Foo(int n) {}
struct Foo(T) {}
template FooType(T) {
static if (is(Unqual!T Unused : Foo!())) {
enum FooType = "Type 1";
} else static if (is(Unqual!T Unused : Foo!n, int n)) {
enum FooType = "Type 2";
} else static if (is(Unqual!T Unused : Foo!U, U)) {
enum FooType = "Type 3";
} else {
enum FooType = "No Foo!";
}
}
Hope this helps.
Look at the Rebindable example again. What I don't understand is how U
can be defined in the else block.
Like your example here. "Unused" isn't defined in the else block,
right..?
Indeed. The thing is - U is basically *set* by the isExpression. It says
'yes, there is such a U, so I'll add it to the local scope.'. This means
that U will be set for the entire scope within which the static if
exists.
Due to the way the criteria are phrased, U is defined when the criteria
are not met, and as such are defined in the else clause instead of the
if clause.
{ // Outer scope starts here.
static if ( !is( const(int) t == const(U), U ) ) {
// isExpression returned false, so U is undefined
} else {
// But here it is defined, because we're still in the same,
// broader scope.
}
}
// And here it's no longer defined.
Was that any better? I admit I didn't understand it at first either, but
then I remembered that static if does not introduce a new scope. That
helped.