Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 29, 2012 Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tove | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | 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 Re: Where does "U" in Rebindable.Rebindable come from? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | 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.
|
Copyright © 1999-2021 by the D Language Foundation