Thread overview | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 02, 2013 Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Take a look at this: http://dpaste.dzfl.pl/6bf578a3 ``` struct Foo {} pragma(msg, Foo.sizeof); void main() {} ``` output: 1LU It seems like structs can't have a size of zero, but this doesn't make a whole lot of sense semantically. I've currently got a project using `std.variant : Algebraic`, so a struct which simply acts as a distinct type would be useful to have. Take, for example, a simple client-server payload passing implementation: ``` enum PayloadType { response_success, response_failure } alias Payload = Algebraic!( ResponseSuccess, ResponseFailure); struct ResponseSuccess { static type = PayloadType.response_success; } struct ResponseFailure { static type = PayloadType.response_failure; uint code; } // Then pseudocode for how the structure is sent over a connection void sendPayload(Resp)(Resp response, OutputStream conn) { conn.write(Resp.type); static if(Resp.sizeof) { // Always triggered, even for empty structs. conn.write(response); } } // And how it's recieved from a connection Payload recievePayload(InputStream conn) { PayloadType type = conn.read!PayloadType(); Payload ret; final switch(type) with(PayloadType) { case response_success: // Nothing actually needs to be read from the stream, // but 1 byte extra is written anyways because ResponseSuccess is 1 byte. ubyte throwaway = conn.read!ubyte(); ret = ResponseSuccess(); break; case response_failure: ResponseFailure failure = conn.read!ResponseFailure(); ret = failure; break; } return ret; } // Usage: auto conn = new InputOutputStream(); //Responds to .read() and .write() conn.sendPayload(ReponseSuccess()); conn.recievePayload().visit!( (ResponseSuccess resp) { writeln("Success!"); }, (ResponseFailure resp) { writeln("Failure! Code: ", resp.code); } )() ``` In the above example, if ResponseSuccess had a size of zero, there would be no additional network overhead. However, because the extra byte of `response` is written to the stream, one must read an empty byte on the recieving end, and throw it away. In this case, it accounts for 33% of the network overhead for transferring a ResponseSuccess structure. 2 bytes for the type of struct, and then 1 additional empty byte... just because. Not to mention that it's not intuitive with how structures normally work. According to individuals in the IRC channel, this is probably due to the implicit void in structs. Can someone shed some light on this? |
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dylan Knutson | My current workaround is to use `Foo.tupleof.length == 0` to detect if a struct has size. But, as you can imagine, this is neither intuitive or optimal. |
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dylan Knutson | On 9/3/13, Dylan Knutson <tcdknutson@gmail.com> wrote:
> Take a look at this:
>
> http://dpaste.dzfl.pl/6bf578a3
I suggest:
-----
void sendPayload(Resp)(Resp response)
{
static if(Resp.sizeof) {
pragma(msg, "has a size");
}
else {
pragma(msg, "has no size");
}
}
void main()
{
sendPayload(cast(void[0])[]);
}
-----
So try to use `void[0]` as a type. When you have such a type, you can initialize it with [], for example:
-----
void[0][int] hash;
void main()
{
hash[1] = [];
assert(1 in hash);
}
-----
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dylan Knutson | On 9/2/2013 4:57 PM, Dylan Knutson wrote:
> Can someone shed some light on this?
It comes from C. This was done in C so that addresses of struct instances will always be unique.
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Tuesday, 3 September 2013 at 00:05:04 UTC, Walter Bright wrote:
> On 9/2/2013 4:57 PM, Dylan Knutson wrote:
>> Can someone shed some light on this?
>
> It comes from C. This was done in C so that addresses of struct instances will always be unique.
Why is that important, and why does D need it?
In C, this might make some sense, however empty structs are much more useful in D, e.g. for metaprogramming.
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On 9/3/13 8:34, Vladimir Panteleev wrote:
> On Tuesday, 3 September 2013 at 00:05:04 UTC, Walter Bright wrote:
>> On 9/2/2013 4:57 PM, Dylan Knutson wrote:
>>> Can someone shed some light on this?
>>
>> It comes from C. This was done in C so that addresses of struct
>> instances will always be unique.
>
> Why is that important, and why does D need it?
>
> In C, this might make some sense, however empty structs are much more
> useful in D, e.g. for metaprogramming.
struct Z {};
Z a, b;
assert(&a != &b);
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | On 9/3/13, Lionello Lunesu <lionello@lunesu.remove.com> wrote:
> struct Z {};
> Z a, b;
> assert(&a != &b);
Since the structs are declared empty, their 1-byte values don't matter. So their addresses don't really matter either.
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | On Tuesday, 3 September 2013 at 02:31:44 UTC, Lionello Lunesu wrote:
> On 9/3/13 8:34, Vladimir Panteleev wrote:
>> On Tuesday, 3 September 2013 at 00:05:04 UTC, Walter Bright wrote:
>>> On 9/2/2013 4:57 PM, Dylan Knutson wrote:
>>>> Can someone shed some light on this?
>>>
>>> It comes from C. This was done in C so that addresses of struct
>>> instances will always be unique.
>>
>> Why is that important, and why does D need it?
>>
>> In C, this might make some sense, however empty structs are much more
>> useful in D, e.g. for metaprogramming.
>
> struct Z {};
> Z a, b;
> assert(&a != &b);
Yes, but why is this important? If you declare Z as "alias int[0] Z", the assert passes, so why is this property needed for structs but not static arrays?
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Tuesday, 3 September 2013 at 03:08:34 UTC, Vladimir Panteleev wrote:
> On Tuesday, 3 September 2013 at 02:31:44 UTC, Lionello Lunesu wrote:
>> On 9/3/13 8:34, Vladimir Panteleev wrote:
>>> On Tuesday, 3 September 2013 at 00:05:04 UTC, Walter Bright wrote:
>>>> On 9/2/2013 4:57 PM, Dylan Knutson wrote:
>>>>> Can someone shed some light on this?
>>>>
>>>> It comes from C. This was done in C so that addresses of struct
>>>> instances will always be unique.
>>>
>>> Why is that important, and why does D need it?
>>>
>>> In C, this might make some sense, however empty structs are much more
>>> useful in D, e.g. for metaprogramming.
>>
>> struct Z {};
>> Z a, b;
>> assert(&a != &b);
>
> Yes, but why is this important? If you declare Z as "alias int[0] Z", the assert passes, so why is this property needed for structs but not static arrays?
alias int[0] Y;
Y.sizeof == 0 // Bug?
Y a;
a.length == 0; // Correct.
This is a bug IMO because the size of Y is 1 byte, not 0.
struct Z{}
Z.sizeof = 1;
Z a,b;
If I see code like this I expect a & b to have different addresses. But then I'm heavily influenced by C/C++. I'd prefer a different syntax, say:
union struct Z{}
or
immutable struct Z{}
either of these reflect that all instances will share the same memory location.
G.
|
September 03, 2013 Re: Structs can't be zero bytes in size? | ||||
---|---|---|---|---|
| ||||
Posted in reply to growler | On Tuesday, 3 September 2013 at 03:57:09 UTC, growler wrote:
> If I see code like this I expect a & b to have different addresses.
Why? What do you need that assumption for? What will break if the structs became 0-sized?
|
Copyright © 1999-2021 by the D Language Foundation