Thread overview
Keeping a mutable reference to a struct with immutable members
May 29, 2016
pineapple
May 29, 2016
pineapple
May 29, 2016
Basile B.
May 29, 2016
pineapple
May 29, 2016
I found another post on this subject and the advice there was "don't put const members in your structs" - http://forum.dlang.org/thread/m87ln2$idv$1@digitalmars.com

This doesn't work out so well when the templated struct is referring to what happens to be a const array.

I thought I could get it done with pointers, but then I realized my data was going out-of-scope. I tried using `Unqual!T thing_i_need_to_reassign_sometimes` where T was immutable but that didn't solve anything, either.

What's the best way to handle something like this?

May 29, 2016
On Sunday, 29 May 2016 at 18:52:36 UTC, pineapple wrote:
> What's the best way to handle something like this?

Well I did get something to work but it's ugly and I refuse to believe there isn't a better way to handle this.

Where `Range` is an alias to a struct with an immutable member, and `this.source` is the attribute that I need to be able to re-assign to a locally scoped return value:

    import core.stdc.stdlib : malloc, free;

    if(this.source) free(source);
    ubyte* newptr = cast(ubyte*) malloc(Range.sizeof);
    assert(newptr !is null, "Failed to allocate memory.");

    Range saved = this.original.save;
    ubyte* savedptr = cast(ubyte*) &saved;
    for(size_t i; i < Range.sizeof; i++){
        newptr[i] = savedptr[i];
    }
    this.source = cast(Range*) newptr;
May 29, 2016
On Sunday, 29 May 2016 at 19:09:13 UTC, pineapple wrote:
> On Sunday, 29 May 2016 at 18:52:36 UTC, pineapple wrote:
>> What's the best way to handle something like this?
>
> Well I did get something to work but it's ugly and I refuse to believe there isn't a better way to handle this.
>
> Where `Range` is an alias to a struct with an immutable member, and `this.source` is the attribute that I need to be able to re-assign to a locally scoped return value:
>
>     this.source = cast(Range*) newptr;

Do yo have a simple, concise runnable example to show ?
May 29, 2016
On Sunday, 29 May 2016 at 19:52:37 UTC, Basile B. wrote:
> Do yo have a simple, concise runnable example to show ?

This is the example I was using to test solutions, it's similar to where I encountered the problem in the first place

    import core.stdc.stdlib : malloc, free;
    import std.stdio;
    import std.range;
    import std.traits;

    struct RepeatRange(Range) if(isForwardRange!Range){
        Range* source;
        Range original;

        this(Range original){
            this.original = original;
            this.repeat(original.save);
        }

        @property auto ref front(){
            return this.source.front;
        }
        void popFront(){
            this.source.popFront();
            if(this.source.empty) this.repeat(this.original.save);
        }

        @nogc void repeat(Range from){
            if(this.source) free(this.source);
            ubyte* newptr = cast(ubyte*) malloc(Range.sizeof);
            assert(newptr !is null, "Failed to allocate memory.");

            ubyte* fromptr = cast(ubyte*) &from;
            for(size_t i; i < Range.sizeof; i++) newptr[i] = fromptr[i];
            this.source = cast(Range*) newptr;
        }

        this(this){
            auto source = *this.source;
            this.source = null;
            this.repeat(source);
        }
        ~this(){
            if(this.source) free(this.source);
        }

        enum bool empty = false;
    }

    struct SomeForwardRange{
        int value = 0;
        const int other = 1; // Immutable member

        enum bool empty = false;
        @property auto ref save(){
            return SomeForwardRange(this.value);
        }
        @property auto ref front(){
            return this.value;
        }
        void popFront(){
            this.value++;
        }
    }

    void main(){
        auto range = RepeatRange!SomeForwardRange(SomeForwardRange(0));
        foreach(item; range.take(10)){
            writeln(item);
        }
    }