Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 28, 2013 Opaque structs | ||||
---|---|---|---|---|
| ||||
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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Anderson | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | 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 Re: Opaque structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | 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.
|
Copyright © 1999-2021 by the D Language Foundation