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.

Reply via email to