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









"growler" <growlercab gmail.com> 