digitalmars.D.learn - Casts and trusted
- Anonymous (57/57) Jun 13 2014 This seems to work from quick testing, but it has casts in
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (16/20) Jun 13 2014 The left-hand side violates a promise: The function takes a slice where
- Anonymous (51/51) Jun 14 2014 That really is it. The other methods are just other gets to the
This seems to work from quick testing, but it has casts in get_ref that I want to avoid. cast(T*) refs[i] is obviously not safe. cast(T*) _buffer[read].ptr doesn't seem necessary, since _buffer[read] is conceivably a T so _buffer[read].ptr should be a T*. But without it I get "Error: cannot implicitly convert expression (&this._buffer[read]) of type const(char)* to char[5]*" I do want to pass in a preallocated buffer to store some pointers, at least as one get option. I also want to disallow modification to the ring buffer through those pointers. How might I rework things to enable that usage while being safe? enum TakeStrategy { cyclic, once } alias TS = TakeStrategy; struct StaticRingBuffer(T, size_t cap) { static assert (cap > 1); private T[cap] _buffer; private size_t _index = cap-1; private size_t _fill = 0; property size_t extra() nothrow const { return cap-fill; } property size_t index() nothrow const { return _index; } property size_t fill() nothrow const { return _fill; } property const ref front() nothrow const { return _buffer[index]; } void put(T ele) pure nothrow { if (index == cap-1) _index = 0; else ++_index; _buffer[index] = ele; if (fill < cap) ++_fill; } void put(T[] eles) pure nothrow { foreach(e; eles) put(e); } trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[] refs) const nothrow { assert(refs.length == n); static if (strat==TS.once) size_t numreads = fixNToFill(n); else size_t numreads = n; size_t read = index; foreach(i;0..numreads) { cast(T*) refs[i] = cast(T*) _buffer[read].ptr; if (read == 0) read = fill-1; else --read; } } private size_t fixNToFill(size_t n) const nothrow { return (n > fill) ? fill : n; } }
Jun 13 2014
On 06/13/2014 06:56 PM, Anonymous wrote:trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[] refs) const nothrow {[...]cast(T*) refs[i] = cast(T*) _buffer[read].ptr;The left-hand side violates a promise: The function takes a slice where the elemenst are const. So, the function says that it will not modify the elements. Also, _buffer[read] is an element, not a slice: private T[cap] _buffer; So, there is no .ptr property. However, perhaps my test code fails to demonstrate your problem: auto s = StaticRingBuffer!(int, 10)(); int i; int*[] arr; arr ~= &i; s.get_ref(0, arr); Please show us complete code. :) Ali
Jun 13 2014
That really is it. The other methods are just other gets to the buffer, like this: T[] get_dup(TS strat=TS.cyclic)(size_t n) const { static if (strat==TS.once) size_t numreads = fixNToFill(n); else size_t numreads = n; auto ret = new T[](numreads); size_t read = index; foreach(i;0..numreads) { ret[i] = _buffer[read].dup; if (read == 0) read = fill-1; else --read; } return ret; } But ah, the .ptr property is not supposed to work for array element? In any case it still works as cast(T*) &(_buffer[read]). Here's the unittest I slapped together: unittest { char[5] hello = "hello"; char[5] world = "world"; char[5] forty = "forty"; char[5] three = "three"; char[5] gdbye = "gdbye"; alias chars_t = char[5]; chars_t[] foo = [hello,world,forty,three]; chars_t[] oob = foo.dup.reverse; StaticRingBuffer!(chars_t,4) bar; bar.put(foo); assert(bar.index==3); const(chars_t)*[4] ptrs; bar.get_ref(4,ptrs); assert(bar.get_dup(4) == oob); foreach(i,ptr; ptrs) assert(*ptr == oob[i]); assert(bar.get_dup(7) == [three,forty,world,hello,three,forty,world]); bar.put("gdbye"); assert(bar.index==0); assert(bar.get_dup(4) == [gdbye,three,forty,world]); assert(bar.get_dup(7) == [gdbye,three,forty,world,gdbye,three,forty]); } But now I see my problem is that a simple const(T*)[N] already initializes its elements to null, so nothing past that should modify them. And without the casts, the type on &(_buffer[read]) is a const(T*) instead of something else which finally makes sense. Somehow I thought .ptr was a property of everything. And now I realize that I can just put the ptr array within the get scope, and return it, to initialize a lhs const(T*)[] by value. I was making things hard on myself by trying to modify a passed-in buffer.
Jun 14 2014