Jump to page: 1 2
Thread overview
Opaque structs
Jun 28, 2013
Andrej Mitrovic
Jun 28, 2013
Brad Anderson
Jun 28, 2013
monarch_dodra
Jun 28, 2013
Johannes Pfau
Jun 28, 2013
Andrej Mitrovic
Jun 29, 2013
Johannes Pfau
Jun 29, 2013
Maxim Fomin
Jun 29, 2013
Johannes Pfau
Jun 29, 2013
monarch_dodra
Jun 29, 2013
Andrej Mitrovic
Jun 29, 2013
monarch_dodra
Jun 30, 2013
Johannes Pfau
Jun 30, 2013
monarch_dodra
June 28, 2013
Traditionally using opaque structs in D when interfacing with C (where one should only ever use such structs with a pointer) are implemented like so:

-----
struct S;

void main()
{
    S* s1;  // ok
    S s2;  // linker error
}
-----

Unfortunately this tends to spawn unreadable error messages:

-----
test.d(3): Error: struct test.S unknown size
test.d(3): Error: struct test.S no size yet for forward reference
test.d(3): Error: struct test.S unknown size
test.d(3): Error: struct test.S no size yet for forward reference
test.d(12): Error: variable test.main.s2 no definition of struct S
test.d(3): Error: struct test.S unknown size
test.d(3): Error: struct test.S no size yet for forward reference
-----

I was thinking we could also implement opaque structs like so:

-----
struct S
{
    @disable this();
    @disable this(this);
}

void main()
{
    S* s1;
    S s2;
}
-----

The error is then:

-----
Error: variable test.main.s2 initializer required for type S
-----

The question is, is a disabled ctor and postblit enough?

Note that if we implement Issue 8728[1], we could even create a better error message via:

-----
struct S
{
    @disable("S is an opaque C type and must only be used as a pointer")
    this();

    @disable("S is an opaque C type and must only be used as a pointer")
    this(this);
}

void main()
{
    S* s1;  // ok
    S s2;  // user error
}
-----

[1] : http://d.puremagic.com/issues/show_bug.cgi?id=8728
June 28, 2013
On Friday, 28 June 2013 at 01:40:44 UTC, Andrej Mitrovic wrote:
> Note that if we implement Issue 8728[1], we could even create a better
> error message via:
>
> -----
> struct S
> {
>     @disable("S is an opaque C type and must only be used as a pointer")
>     this();
>
>     @disable("S is an opaque C type and must only be used as a pointer")
>     this(this);
> }
>
> void main()
> {
>     S* s1;  // ok
>     S s2;  // user error
> }
> -----
>
> [1] : http://d.puremagic.com/issues/show_bug.cgi?id=8728

+1.  Anything that makes error messages clearer is a win in my book and there is precedents for it in @deprecate(msg) which was a clear win.
June 28, 2013
On Friday, 28 June 2013 at 02:17:06 UTC, Brad Anderson wrote:
> On Friday, 28 June 2013 at 01:40:44 UTC, Andrej Mitrovic wrote:
>> Note that if we implement Issue 8728[1], we could even create a better
>> error message via:
>>
>> -----
>> struct S
>> {
>>    @disable("S is an opaque C type and must only be used as a pointer")
>>    this();
>>
>>    @disable("S is an opaque C type and must only be used as a pointer")
>>    this(this);
>> }
>>
>> void main()
>> {
>>    S* s1;  // ok
>>    S s2;  // user error
>> }
>> -----
>>
>> [1] : http://d.puremagic.com/issues/show_bug.cgi?id=8728
>
> +1.  Anything that makes error messages clearer is a win in my book and there is precedents for it in @deprecate(msg) which was a clear win.

+1 also. I was going to say "deprecated does it that way, so should disable", but that's already in the ticket ^^
June 28, 2013
Am Fri, 28 Jun 2013 03:40:31 +0200
schrieb Andrej Mitrovic <andrej.mitrovich@gmail.com>:

> struct S
> {
>     @disable("S is an opaque C type and must only be used as a
> pointer") this();
> 
>     @disable("S is an opaque C type and must only be used as a
> pointer") this(this);
> }

A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly?
June 28, 2013
On 6/28/13, Johannes Pfau <nospam@example.com> wrote:
> A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly?

Because the user should never be able to use such a struct by value, in other words a user might mistakenly write code such as:

-----
struct S { }

extern(C) S* get();
extern(C) void call(S*);

void main()
{
    S* s = getS();

    S s2 = *s;  // copies 1 byte
    call(&s2);  // no telling what will happen on the C side, usually
memory corruption + crash
}
-----
June 29, 2013
Am Fri, 28 Jun 2013 22:16:33 +0200
schrieb Andrej Mitrovic <andrej.mitrovich@gmail.com>:

> On 6/28/13, Johannes Pfau <nospam@example.com> wrote:
> > A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly?
> 
> Because the user should never be able to use such a struct by value, in other words a user might mistakenly write code such as:
> 
>     S s2 = *s;  // copies 1 byte

But why is that legal / does that copy _one_ byte? It seems like that's
totally arbitrary. Shouldn't doing anything value-related on
an empty struct be invalid anyway?


June 29, 2013
On Saturday, 29 June 2013 at 08:01:17 UTC, Johannes Pfau wrote:
> Am Fri, 28 Jun 2013 22:16:33 +0200
> schrieb Andrej Mitrovic <andrej.mitrovich@gmail.com>:
>
>> On 6/28/13, Johannes Pfau <nospam@example.com> wrote:
>> > A naive question: Why isn't struct S {} enough? This should be a
>> > struct with size 0 so why do we need to disable the constructor and
>> > postblit explicitly?
>> 
>> Because the user should never be able to use such a struct by value,
>> in other words a user might mistakenly write code such as:
>> 
>>     S s2 = *s;  // copies 1 byte
>
> But why is that legal / does that copy _one_ byte? It seems like that's
> totally arbitrary. Shouldn't doing anything value-related on
> an empty struct be invalid anyway?

It copies one byte because empty structs have one byte - according to D implementation. The value can be adjusted using align() atrribute.
June 29, 2013
Am Sat, 29 Jun 2013 10:54:32 +0200
schrieb "Maxim Fomin" <maxim@maxim-fomin.ru>:

> On Saturday, 29 June 2013 at 08:01:17 UTC, Johannes Pfau wrote:
> > Am Fri, 28 Jun 2013 22:16:33 +0200
> > schrieb Andrej Mitrovic <andrej.mitrovich@gmail.com>:
> >
> >> On 6/28/13, Johannes Pfau <nospam@example.com> wrote:
> >> > A naive question: Why isn't struct S {} enough? This should
> >> > be a
> >> > struct with size 0 so why do we need to disable the
> >> > constructor and
> >> > postblit explicitly?
> >> 
> >> Because the user should never be able to use such a struct by
> >> value,
> >> in other words a user might mistakenly write code such as:
> >> 
> >>     S s2 = *s;  // copies 1 byte
> >
> > But why is that legal / does that copy _one_ byte? It seems
> > like that's
> > totally arbitrary. Shouldn't doing anything value-related on
> > an empty struct be invalid anyway?
> 
> It copies one byte because empty structs have one byte - according to D implementation. The value can be adjusted using align() atrribute.

I see. I didn't know that we have this in the spec, but I guess there's some good reason for this behavior if it was explicitly specified / implemented.
June 29, 2013
On 6/29/13, Johannes Pfau <nospam@example.com> wrote:
> Shouldn't doing anything value-related on
> an empty struct be invalid anyway?

Maybe, maybe not. I could imagine it would cause problems if we simply disallowed it, e.g. if you want to copy attributes from one declaration to another.
June 29, 2013
On Saturday, 29 June 2013 at 12:58:51 UTC, Johannes Pfau wrote:
> Am Sat, 29 Jun 2013 10:54:32 +0200
> schrieb "Maxim Fomin" <maxim@maxim-fomin.ru>:
>
>> On Saturday, 29 June 2013 at 08:01:17 UTC, Johannes Pfau wrote:
>> > Am Fri, 28 Jun 2013 22:16:33 +0200
>> > schrieb Andrej Mitrovic <andrej.mitrovich@gmail.com>:
>> >
>> >> On 6/28/13, Johannes Pfau <nospam@example.com> wrote:
>> >> > A naive question: Why isn't struct S {} enough? This should be a
>> >> > struct with size 0 so why do we need to disable the constructor and
>> >> > postblit explicitly?
>> >> 
>> >> Because the user should never be able to use such a struct by value,
>> >> in other words a user might mistakenly write code such as:
>> >> 
>> >>     S s2 = *s;  // copies 1 byte
>> >
>> > But why is that legal / does that copy _one_ byte? It seems like that's
>> > totally arbitrary. Shouldn't doing anything value-related on
>> > an empty struct be invalid anyway?
>> 
>> It copies one byte because empty structs have one byte - according to D implementation. The value can be adjusted using align() atrribute.
>
> I see. I didn't know that we have this in the spec, but I guess there's
> some good reason for this behavior if it was explicitly specified /
> implemented.

For the same reasons as in C/C++, "[they] require empty classes to have non-zero size to ensure object identity". For example, calculating the size of an array using:
"size_t size = sizeof(arr) / sizeof(arr[0])"
Requires the object's size to be non null.

Iterating with:
s* it = arr;
s* it_end = arr + size;
for ( ; it != it_end ; ++it )
{}
Requires the objects to take up space.

« First   ‹ Prev
1 2