Jump to page: 1 2
Thread overview
typedef behavior
Feb 09, 2018
Alex
Feb 10, 2018
Ali Çehreli
Feb 10, 2018
Alex
Feb 10, 2018
Ali Çehreli
Feb 10, 2018
Alex
Feb 10, 2018
Alex
Feb 11, 2018
Alex
Feb 11, 2018
Simen Kjærås
Feb 11, 2018
Alex
Feb 12, 2018
Simen Kjærås
Feb 12, 2018
Alex
Feb 12, 2018
Simen Kjærås
Feb 12, 2018
Alex
Feb 12, 2018
Simen Kjærås
Feb 12, 2018
Alex
February 09, 2018
A question about Typedef usage:
Say, I have the following circumstances

/// --- code --- ///

import std.typecons;

void main()
{
	MyEA ea;
	MyEB eb;
	ea.tarr.length = 5;
	static assert(!is(MyEA == MyEB));
	static assert(!is(MyEA == E));
	static assert(!is(MyEB == E));
	assert(ea.tarr.length == eb.tarr.length); // line 11
	assert(ea.tarr.length != eb.tarr.length); // line 12
}

struct T
{
	size_t i;
}

struct E
{
	size_t i;
	static T[] tarr;
}

alias MyEA = Typedef!(E, E.init, "A"); // line 26
alias MyEB = Typedef!(E, E.init, "B"); // line 27

/// --- code ends --- ///

Line 12 yields an assertion error, while line 11 does not.
This tells me, that despite the fact the types MyEA and MyEB are different they still share the static array, which would contradict the definition of static.

I suppose, the tricky thing is to tweak the init property of the typedefs in lines 26/27 to avoid this clash. How to manage this?
February 09, 2018
On 02/09/2018 03:45 PM, Alex wrote:
> A question about Typedef usage:
> Say, I have the following circumstances
>
> /// --- code --- ///
>
> import std.typecons;
>
> void main()
> {
>      MyEA ea;
>      MyEB eb;
>      ea.tarr.length = 5;
>      static assert(!is(MyEA == MyEB));
>      static assert(!is(MyEA == E));
>      static assert(!is(MyEB == E));
>      assert(ea.tarr.length == eb.tarr.length); // line 11
>      assert(ea.tarr.length != eb.tarr.length); // line 12

You must have meant

     assert(ea.tarr.ptr != eb.tarr.ptr); // line 12

Indeed, .ptr are unexpectedly the same.

> }
>
> struct T
> {
>      size_t i;
> }
>
> struct E
> {
>      size_t i;
>      static T[] tarr;

To save time to others, note that 'tarr' is a static member that ends up being shared by two Typedef instantiations.

> }
>
> alias MyEA = Typedef!(E, E.init, "A"); // line 26
> alias MyEB = Typedef!(E, E.init, "B"); // line 27
>
> /// --- code ends --- ///
>
> Line 12 yields an assertion error, while line 11 does not.
> This tells me, that despite the fact the types MyEA and MyEB are
> different they still share the static array, which would contradict the
> definition of static.
>
> I suppose, the tricky thing is to tweak the init property of the
> typedefs in lines 26/27 to avoid this clash. How to manage this?

Ali

February 10, 2018
On Saturday, 10 February 2018 at 01:01:39 UTC, Ali Çehreli wrote:
> On 02/09/2018 03:45 PM, Alex wrote:
> > A question about Typedef usage:
> > Say, I have the following circumstances
> >
> > /// --- code --- ///
> >
> > import std.typecons;
> >
> > void main()
> > {
> >      MyEA ea;
> >      MyEB eb;
> >      ea.tarr.length = 5;
> >      static assert(!is(MyEA == MyEB));
> >      static assert(!is(MyEA == E));
> >      static assert(!is(MyEB == E));
> >      assert(ea.tarr.length == eb.tarr.length); // line 11
> >      assert(ea.tarr.length != eb.tarr.length); // line 12
>
> You must have meant
>
>      assert(ea.tarr.ptr != eb.tarr.ptr); // line 12
>
> Indeed, .ptr are unexpectedly the same.
>

Yes... this is a more precise comparison :)

> > }
> >
> > struct T
> > {
> >      size_t i;
> > }
> >
> > struct E
> > {
> >      size_t i;
> >      static T[] tarr;
>
> To save time to others, note that 'tarr' is a static member that ends up being shared by two Typedef instantiations.

Yup. They are shared by two Typedef instantiations with different cookies.

So...
The question is two-fold:
Would it help to alter the init value of the Typedef?
If yes, how to alter it?
If no, is this a bug?

>
> > }
> >
> > alias MyEA = Typedef!(E, E.init, "A"); // line 26
> > alias MyEB = Typedef!(E, E.init, "B"); // line 27
> >
> > /// --- code ends --- ///
> >
> > Line 12 yields an assertion error, while line 11 does not.
> > This tells me, that despite the fact the types MyEA and MyEB
> are
> > different they still share the static array, which would
> contradict the
> > definition of static.
> >
> > I suppose, the tricky thing is to tweak the init property of
> the
> > typedefs in lines 26/27 to avoid this clash. How to manage
> this?
>
> Ali
February 09, 2018
On 02/09/2018 05:14 PM, Alex wrote:

>> > struct E
>> > {
>> >      size_t i;
>> >      static T[] tarr;
>>
>> To save time to others, note that 'tarr' is a static member that ends
>> up being shared by two Typedef instantiations.
>
> Yup. They are shared by two Typedef instantiations with different cookies.
>
> So...
> The question is two-fold:
> Would it help to alter the init value of the Typedef?
> If yes, how to alter it?
> If no, is this a bug?

I think this is a limitation of Typedef.

I can't see a way out (at least one that can support any type E). It should be possible if you can modify E but I can't work something out now.

Ali

February 10, 2018
On Saturday, 10 February 2018 at 01:23:20 UTC, Ali Çehreli wrote:
> >
> > Yup. They are shared by two Typedef instantiations with
> different cookies.
> >
> > So...
> > The question is two-fold:
> > Would it help to alter the init value of the Typedef?
> > If yes, how to alter it?
> > If no, is this a bug?
>
> I think this is a limitation of Typedef.
>
> I can't see a way out (at least one that can support any type E). It should be possible if you can modify E but I can't work something out now.
>
> Ali

Ah... From your hint I arrived at the following:

Inside of the struct E I define more then one static array. Namely, one for each Typedef I plan to instantiate. The Typedefs have to be known at compile time, so the amount of them has to be known by me :)
Then, during the initialization, I work only with one of the arrays of E, depending on the Typedef I use.
During the work inside of E, the object will have to check, which array was initialized and cooperate with this array, as this is the only possibility.

As a workaround this will work, I think... Thanks!

Nevertheless, I would file a bug later on... all ideas are appreciated in the meanwhile.
February 10, 2018
On Saturday, 10 February 2018 at 02:08:50 UTC, Alex wrote:
> Inside of the struct E I define more then one static array. Namely, one for each Typedef I plan to instantiate. The Typedefs have to be known at compile time, so the amount of them has to be known by me :)
> Then, during the initialization, I work only with one of the arrays of E, depending on the Typedef I use.
> During the work inside of E, the object will have to check, which array was initialized and cooperate with this array, as this is the only possibility.

Hmm... No. As the arrays are shared all of them will be initialized for every Typedef and the last point (decision during the work inside of a single Typedef) can not be achieved. So... there has to be another indirection, which will be filled during (possibly static) initialization.
February 11, 2018
On Saturday, 10 February 2018 at 02:55:26 UTC, Alex wrote:

bug filed

https://issues.dlang.org/show_bug.cgi?id=18416

February 11, 2018
On Sunday, 11 February 2018 at 01:32:52 UTC, Alex wrote:
> On Saturday, 10 February 2018 at 02:55:26 UTC, Alex wrote:
>
> bug filed
>
> https://issues.dlang.org/show_bug.cgi?id=18416

Basically, Typedef looks like this:

struct Typedef(T) {
    T _payload;
    // Forward method calls, member access, etc, to _payload.
}

If T looks like this:

struct T {
    static int[3] arr;
    void foo() { arr[0]++; }
}

How is Typedef supposed to wrap T.foo in such a way that it uses a different arr depending on whether it's called from the Typedef or from T?

--
  Simen
February 11, 2018
On Sunday, 11 February 2018 at 15:18:11 UTC, Simen Kjærås wrote:
>
> Basically, Typedef looks like this:
>
> struct Typedef(T) {
>     T _payload;
>     // Forward method calls, member access, etc, to _payload.
> }
>
> If T looks like this:
>
> struct T {
>     static int[3] arr;
>     void foo() { arr[0]++; }
> }
>
> How is Typedef supposed to wrap T.foo in such a way that it uses a different arr depending on whether it's called from the Typedef or from T?
>
> --
>   Simen

In the same way as it is handled by this:

/// --- code --- ///

void main(){}

static assert(T.arr.ptr != S.arr.ptr);

struct T {
    static int[3] arr;
    void foo() { arr[0]++; }
}

struct S {
    static int[3] arr;
    void foo() { arr[0]++; }
}

/// --- code ends --- ///

I understand that Typedef should be kept simple. But if it defines a type which is recognized as another type in respect to the underlying one, then I should be able to rely on independence of everything, like I would copy/paste the implementation. Or do I misinterpret something?
February 12, 2018
On Sunday, 11 February 2018 at 19:33:23 UTC, Alex wrote:
> On Sunday, 11 February 2018 at 15:18:11 UTC, Simen Kjærås wrote:
>>
>> Basically, Typedef looks like this:
>>
>> struct Typedef(T) {
>>     T _payload;
>>     // Forward method calls, member access, etc, to _payload.
>> }
>>
>> If T looks like this:
>>
>> struct T {
>>     static int[3] arr;
>>     void foo() { arr[0]++; }
>> }
>>
>> How is Typedef supposed to wrap T.foo in such a way that it uses a different arr depending on whether it's called from the Typedef or from T?
>>
>> --
>>   Simen
>
> In the same way as it is handled by this:
>
> /// --- code --- ///
>
> void main(){}
>
> static assert(T.arr.ptr != S.arr.ptr);
>
> struct T {
>     static int[3] arr;
>     void foo() { arr[0]++; }
> }
>
> struct S {
>     static int[3] arr;
>     void foo() { arr[0]++; }
> }
>
> /// --- code ends --- ///
>
> I understand that Typedef should be kept simple. But if it defines a type which is recognized as another type in respect to the underlying one, then I should be able to rely on independence of everything, like I would copy/paste the implementation. Or do I misinterpret something?

I agree that'd be nice. Sadly, it's not a reasonable expectation. :(

A more extreme example: You have a compiled library, and some .di (header) files. In one of those files is this code:

struct S {
    static int[] arr;
    void foo();
}

Now how should Typedef go about making foo() do the right thing? Even with compiler support, this is impossible - the source of S.foo is simply not available, and it doesn't take the address of the static data as a parameter anywhere.

--
  Simen
« First   ‹ Prev
1 2