Jump to page: 1 2
Thread overview
Where does "U" in Rebindable.Rebindable come from?
Mar 29, 2012
simendsjo
Mar 29, 2012
Tove
Mar 29, 2012
Ali Çehreli
Mar 29, 2012
Simen Kjærås
Mar 30, 2012
simendsjo
Mar 30, 2012
Simen Kjærås
Mar 30, 2012
simendsjo
Apr 01, 2012
Simen Kjærås
Mar 30, 2012
Philippe Sigaud
Mar 30, 2012
Timon Gehr
Mar 31, 2012
Philippe Sigaud
March 29, 2012
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))
    {
    }
    else
    {
        static assert(is(typeof(U))); // false, U not defined
    }
}


And std.typecons.Rebindable:

template Rebindable(T) if (is(T == class) || is(T == interface) || isArray!(T))
{
    static if (!is(T X == const(U), U) && !is(T X == immutable(U), U))
    {
        alias T Rebindable;
    }
    else static if (isArray!(T))
    {
        alias const(ElementType!(T))[] Rebindable;
    }
    else
    {
        struct Rebindable
        {
            private union
            {
                T original;
                U stripped;
            }
            void opAssign(T another) pure nothrow
            {
                stripped = cast(U) another;
            }
            void opAssign(Rebindable another) pure nothrow
            {
                stripped = another.stripped;
            }
            static if (is(T == const U))
            {
                // safely assign immutable to const
                void opAssign(Rebindable!(immutable U) another) pure nothrow
                {
                    stripped = another.stripped;
                }
            }

            this(T initializer) pure nothrow
            {
                opAssign(initializer);
            }

            @property ref T get() pure nothrow
            {
                return original;
            }
            @property ref const(T) get() const pure nothrow
            {
                return original;
            }

            alias get this;
        }
    }
}
March 29, 2012
On Thursday, 29 March 2012 at 20:15:43 UTC, simendsjo 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))
>     {
>     }
>     else
>     {
>         static assert(is(typeof(U))); // false, U not defined
>     }
> }
>

magic pattern matching...

import std.stdio;

void main()
{
    static if(is(int x == const(U), U))
      writeln("Mutable: " ~ U.stringof);
    else static if(is(const int x == const(U), U))
      writeln("Const: " ~ U.stringof);
}

March 29, 2012
On 03/29/2012 01:51 PM, Tove wrote:
> On Thursday, 29 March 2012 at 20:15:43 UTC, simendsjo 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))
>> {
>> }
>> else
>> {
>> static assert(is(typeof(U))); // false, U not defined
>> }
>> }
>>
>
> magic pattern matching...
>
> import std.stdio;
>
> void main()
> {
> static if(is(int x == const(U), U))
> writeln("Mutable: " ~ U.stringof);
> else static if(is(const int x == const(U), U))
> writeln("Const: " ~ U.stringof);
> }
>

Some uses of the 'is' expression have been the most magical (read: difficult) part of D for me. :) I am still not sure that I understand it correctly. ;)

  http://dlang.org/expression.html#IsExpression

Ali
March 29, 2012
On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo@gmail.com> 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.
March 30, 2012
On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kjærås <simen.kjaras@gmail.com> wrote:

> On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo@gmail.com> 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..?
March 30, 2012
On Fri, 30 Mar 2012 15:03:49 +0200, simendsjo <simendsjo@gmail.com> wrote:

> On Fri, 30 Mar 2012 01:09:06 +0200, Simen Kjærås <simen.kjaras@gmail.com> wrote:
>
>> On Thu, 29 Mar 2012 22:15:41 +0200, simendsjo <simendsjo@gmail.com> 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.
March 30, 2012
On Fri, 30 Mar 2012 17:13:25 +0200, Simen Kjærås <simen.kjaras@gmail.com> wrote:
>
> 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.

I knew static if didn't create a new scope, but I still thought U would not be defined if it didn't match, but it seems it is defined just by existing in the scope.
I had a bug when I tried to reproduce the behavior: I used typeof(U), which is, of course, not possible as U is a type :)

Thanks for the explanation. Allowed to use D at work yet btw?
March 30, 2012
On Fri, Mar 30, 2012 at 01:09, Simen Kjærås <simen.kjaras@gmail.com> wrote:
> The same pattern is used in std.typecons.isTuple:
>
> template isTuple(T)
> {
>    static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
>    {

Wait, does that work now? They added 'is(XXX, YYY...)'?
March 30, 2012
On 03/30/2012 09:20 PM, Philippe Sigaud wrote:
> On Fri, Mar 30, 2012 at 01:09, Simen Kjærås<simen.kjaras@gmail.com>  wrote:
>> The same pattern is used in std.typecons.isTuple:
>>
>> template isTuple(T)
>> {
>>     static if (is(Unqual!T Unused : Tuple!Specs, Specs...))
>>     {
>
> Wait, does that work now?

Yes.

> They added 'is(XXX, YYY...)'?

The syntax is static if(is(XXX Unused, YYY...)). (Where Unused is something you never have any use for.)
March 31, 2012
On Fri, Mar 30, 2012 at 23:00, Timon Gehr <timon.gehr@gmx.ch> wrote:
>> Wait, does that work now?
>
>
> Yes.
>
>
>> They added 'is(XXX, YYY...)'?
>
>
> The syntax is static if(is(XXX Unused, YYY...)). (Where Unused is something
> you never have any use for.)

OK, time to update my template tutorial, then.
« First   ‹ Prev
1 2