digitalmars.D.learn - Cleverness of the compiler
- Namespace (53/53) Nov 24 2013 I love this feature, but I'm unsure how it works. Can someone
- growler (9/62) Nov 24 2013 All the calls to 'at' are using T=int (implied), as far as I can
- growler (2/74) Nov 24 2013 Sorry, T=int should be T=int*
- Namespace (9/9) Nov 24 2013 I meant the function:
- Shammah Chancellor (23/26) Nov 24 2013 It doesn't work. That code is buggy. It's overwriting previous
- Namespace (3/32) Nov 25 2013 Ok, that calms me down. Thought I had missed something.
- Shammah Chancellor (7/39) Nov 25 2013 Yeah. You had me confused for a bit too. :) Couldn't figure out why
I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*. ---- import std.stdio; import core.stdc.stdlib : calloc, realloc, free; import core.stdc.string : memcpy; struct Tarray { void* ptr; size_t length; size_t capacity; ~this() { .free(this.ptr); this.ptr = null; } } void push(T)(ref Tarray arr, T elem) { if (arr.length == arr.capacity) arr.reserve(T.sizeof); memcpy(&arr.ptr[arr.length++], &elem, T.sizeof); } void reserve(ref Tarray arr, size_t typeOf, size_t cap = 0) { if (arr.capacity != 0) { arr.capacity = cap == 0 ? (arr.capacity * 2) + 1 : arr.capacity + cap; arr.ptr = .realloc(arr.ptr, arr.capacity * typeOf); } else { arr.capacity = cap == 0 ? 3 : cap; arr.ptr = .calloc(arr.capacity, typeOf); } } void at(T)(ref Tarray arr, size_t index, T* elem) { if (index >= arr.length || elem is null) return; memcpy(elem, &arr.ptr[index], T.sizeof); } void main() { Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(ushort.max + 1); arr.at(3, &a); writeln(a, "::", arr.length, "::", arr.capacity); } ----
Nov 24 2013
On Monday, 25 November 2013 at 00:08:52 UTC, Namespace wrote:I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*. ---- import std.stdio; import core.stdc.stdlib : calloc, realloc, free; import core.stdc.string : memcpy; struct Tarray { void* ptr; size_t length; size_t capacity; ~this() { .free(this.ptr); this.ptr = null; } } void push(T)(ref Tarray arr, T elem) { if (arr.length == arr.capacity) arr.reserve(T.sizeof); memcpy(&arr.ptr[arr.length++], &elem, T.sizeof); } void reserve(ref Tarray arr, size_t typeOf, size_t cap = 0) { if (arr.capacity != 0) { arr.capacity = cap == 0 ? (arr.capacity * 2) + 1 : arr.capacity + cap; arr.ptr = .realloc(arr.ptr, arr.capacity * typeOf); } else { arr.capacity = cap == 0 ? 3 : cap; arr.ptr = .calloc(arr.capacity, typeOf); } } void at(T)(ref Tarray arr, size_t index, T* elem) { if (index >= arr.length || elem is null) return; memcpy(elem, &arr.ptr[index], T.sizeof); } void main() { Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(ushort.max + 1); arr.at(3, &a); writeln(a, "::", arr.length, "::", arr.capacity); } ----All the calls to 'at' are using T=int (implied), as far as I can tell. ... int a; ... arr.at(0, &a); // tyepof(a) is int so in 'at' T.sizeof = 4. Is this the call to 'at' you're referring to? Cheers
Nov 24 2013
On Monday, 25 November 2013 at 00:51:47 UTC, growler wrote:On Monday, 25 November 2013 at 00:08:52 UTC, Namespace wrote:Sorry, T=int should be T=int*I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*. ---- import std.stdio; import core.stdc.stdlib : calloc, realloc, free; import core.stdc.string : memcpy; struct Tarray { void* ptr; size_t length; size_t capacity; ~this() { .free(this.ptr); this.ptr = null; } } void push(T)(ref Tarray arr, T elem) { if (arr.length == arr.capacity) arr.reserve(T.sizeof); memcpy(&arr.ptr[arr.length++], &elem, T.sizeof); } void reserve(ref Tarray arr, size_t typeOf, size_t cap = 0) { if (arr.capacity != 0) { arr.capacity = cap == 0 ? (arr.capacity * 2) + 1 : arr.capacity + cap; arr.ptr = .realloc(arr.ptr, arr.capacity * typeOf); } else { arr.capacity = cap == 0 ? 3 : cap; arr.ptr = .calloc(arr.capacity, typeOf); } } void at(T)(ref Tarray arr, size_t index, T* elem) { if (index >= arr.length || elem is null) return; memcpy(elem, &arr.ptr[index], T.sizeof); } void main() { Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(ushort.max + 1); arr.at(3, &a); writeln(a, "::", arr.length, "::", arr.capacity); } ----All the calls to 'at' are using T=int (implied), as far as I can tell. ... int a; ... arr.at(0, &a); // tyepof(a) is int so in 'at' T.sizeof = 4. Is this the call to 'at' you're referring to? Cheers
Nov 24 2013
I meant the function: ---- void at(T)(ref Tarray arr, size_t index, T* elem) { if (index >= arr.length || elem is null) return; memcpy(elem, &arr.ptr[index], T.sizeof); } ---- -> arr.ptr[index]
Nov 24 2013
On 2013-11-25 00:08:50 +0000, Namespace said:I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*.It doesn't work. That code is buggy. It's overwriting previous elements with new ones. Indexing a void* only moves up by 1 byte. void main() { pragma(msg, void.sizeof) Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); writeln(arr.capacity); arr.push(ushort.max); //Write a ushort to test. arr.at(3, &a); //Only works because we're on a little endian platform writeln(a, "::", arr.length, "::", arr.capacity); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); }
Nov 24 2013
On Monday, 25 November 2013 at 03:13:48 UTC, Shammah Chancellor wrote:On 2013-11-25 00:08:50 +0000, Namespace said:Ok, that calms me down. Thought I had missed something.I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*.It doesn't work. That code is buggy. It's overwriting previous elements with new ones. Indexing a void* only moves up by 1 byte. void main() { pragma(msg, void.sizeof) Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); writeln(arr.capacity); arr.push(ushort.max); //Write a ushort to test. arr.at(3, &a); //Only works because we're on a little endian platform writeln(a, "::", arr.length, "::", arr.capacity); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); }
Nov 25 2013
On 2013-11-25 10:34:39 +0000, Namespace said:On Monday, 25 November 2013 at 03:13:48 UTC, Shammah Chancellor wrote:Yeah. You had me confused for a bit too. :) Couldn't figure out why Ushort.max was being re-read correctly. I'm use to big-endian platforms. It certainly would have been miraculous if the compiler knew what kind of elements you put in the array to be able to index to the right location. -ShammahOn 2013-11-25 00:08:50 +0000, Namespace said:Ok, that calms me down. Thought I had missed something.I love this feature, but I'm unsure how it works. Can someone explain me, how the compiler deduce that he should read 4 bytes for each index (the 'at' function)? The type is void*, not int*.It doesn't work. That code is buggy. It's overwriting previous elements with new ones. Indexing a void* only moves up by 1 byte. void main() { pragma(msg, void.sizeof) Tarray arr; arr.push(42); int a; arr.at(0, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(23); arr.at(1, &a); writeln(a, "::", arr.length, "::", arr.capacity); arr.push(1337); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); writeln(arr.capacity); arr.push(ushort.max); //Write a ushort to test. arr.at(3, &a); //Only works because we're on a little endian platform writeln(a, "::", arr.length, "::", arr.capacity); arr.at(2, &a); writeln(a, "::", arr.length, "::", arr.capacity); }
Nov 25 2013