Jump to page: 1 2 3
Thread overview
Structs can't be zero bytes in size?
Sep 02, 2013
Dylan Knutson
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Andrej Mitrovic
Sep 03, 2013
Walter Bright
Sep 03, 2013
Vladimir Panteleev
Sep 03, 2013
Lionello Lunesu
Sep 03, 2013
Andrej Mitrovic
Sep 04, 2013
Lionello Lunesu
Sep 03, 2013
Vladimir Panteleev
Sep 03, 2013
growler
Sep 03, 2013
Vladimir Panteleev
Sep 03, 2013
growler
Sep 03, 2013
Walter Bright
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Walter Bright
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Piotr Szturmaj
Sep 03, 2013
Walter Bright
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Walter Bright
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Andrej Mitrovic
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Dylan Knutson
Sep 03, 2013
Walter Bright
Sep 03, 2013
Ali Çehreli
Sep 03, 2013
Walter Bright
September 02, 2013
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
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
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
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
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
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
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
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
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
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?
« First   ‹ Prev
1 2 3