Thread overview
port C++ to D - copy constness
Jun 02, 2014
dennis luehring
Jun 02, 2014
Timon Gehr
Jun 02, 2014
dennis luehring
June 02, 2014
i want to port this C++ code to good/clean D and have no real idea how to start

contains 2 templates - a slice like and a binary reader for an slice
main idea was to copy the immutablity of the slice data to the reader

http://pastebin.com/XX2yhm8D

the example compiles fine with http://gcc.godbolt.org/, clang version 3.4.1 and compiler-options: -O2 -std=c++11

the slice_T template - could be maybe reduce down to an normal D slice
but i want to control the slice (im)mutability - so maybe there is still a need for the slice_T thing

i don't know if the binary reader read_ref method should be written totaly different in D

any tips, ideas?



June 02, 2014
On 06/02/2014 09:06 AM, dennis luehring wrote:
> i want to port this C++ code to good/clean D and have no real idea how
> to start
>
> contains 2 templates - a slice like and a binary reader for an slice
> main idea was to copy the immutablity of the slice data to the reader
>
> http://pastebin.com/XX2yhm8D
>
> the example compiles fine with http://gcc.godbolt.org/, clang version
> 3.4.1 and compiler-options: -O2 -std=c++11
>
> the slice_T template - could be maybe reduce down to an normal D slice
> but i want to control the slice (im)mutability - so maybe there is still
> a need for the slice_T thing
>
> i don't know if the binary reader read_ref method should be written
> totaly different in D
>
> any tips, ideas?
>

If the following is not already what you were looking for, it should get you started. (But note that the interface provided by BinaryReader is unsafe: It may invent pointers. You might want to add template constraints that would at least allow the implementation to be @trusted.)

template CopyQualifiers(S,T){
    import std.traits;
    static if(is(S==const)) alias T1=const(Unqual!T);
    else alias T1=Unqual!T;
    static if(is(S==immutable)) alias T2=immutable(T1);
    else alias T2=T1;
    static if(is(S==inout)) alias T3=inout(T2);
    else alias T3=T2;
    static if(is(S==shared)) alias CopyQualifiers=shared(T3);
    else alias CopyQualifiers=T3;
}

struct BinaryReader(T){
    @disable this();
    this(T[] slice){ this.slice=slice; }
    size_t left()const{ return slice.length - offset; }
    bool enoughSpaceLeft(size_t size)const{ return size <= left(); }
    ref readRef(V)(){
        if(!enoughSpaceLeft(V.sizeof)) throw new Exception("1");
        auto off=offset;
        offset+=V.sizeof;
        return *cast(CopyQualifiers!(T,V)*)(slice.ptr+off);
    }
    auto readValue(V)(){ return readRef!V(); }
private:
    T[] slice;
    size_t offset=0;
}

auto binaryReader(T)(T[] slice){ return BinaryReader!T(slice); }

void main(){
    import std.stdio;
    try{
        auto testData = "THIS IS BINARY TEST DATA"; // no comment
        auto stream = binaryReader(testData);
        static assert(is(typeof(stream.readRef!uint())==immutable));
        (ref ref_){
            auto value = stream.readValue!uint();
        }(stream.readRef!uint());
    }catch(Exception e){
        writeln("exception error: ",e.msg);
    }catch{
        writeln("exception unknown");
    }
}


June 02, 2014
Am 02.06.2014 12:09, schrieb Timon Gehr:
> On 06/02/2014 09:06 AM, dennis luehring wrote:
>> i want to port this C++ code to good/clean D and have no real idea how
>> to start
>>
>> contains 2 templates - a slice like and a binary reader for an slice
>> main idea was to copy the immutablity of the slice data to the reader
>>
>> http://pastebin.com/XX2yhm8D
>>
>> the example compiles fine with http://gcc.godbolt.org/, clang version
>> 3.4.1 and compiler-options: -O2 -std=c++11
>>
>> the slice_T template - could be maybe reduce down to an normal D slice
>> but i want to control the slice (im)mutability - so maybe there is still
>> a need for the slice_T thing
>>
>> i don't know if the binary reader read_ref method should be written
>> totaly different in D
>>
>> any tips, ideas?
>>
>
> If the following is not already what you were looking for, it should get
> you started. (But note that the interface provided by BinaryReader is
> unsafe: It may invent pointers. You might want to add template
> constraints that would at least allow the implementation to be @trusted.)
>
> template CopyQualifiers(S,T){
>       import std.traits;
>       static if(is(S==const)) alias T1=const(Unqual!T);
>       else alias T1=Unqual!T;
>       static if(is(S==immutable)) alias T2=immutable(T1);
>       else alias T2=T1;
>       static if(is(S==inout)) alias T3=inout(T2);
>       else alias T3=T2;
>       static if(is(S==shared)) alias CopyQualifiers=shared(T3);
>       else alias CopyQualifiers=T3;
> }
>
> struct BinaryReader(T){
>       @disable this();
>       this(T[] slice){ this.slice=slice; }
>       size_t left()const{ return slice.length - offset; }
>       bool enoughSpaceLeft(size_t size)const{ return size <= left(); }
>       ref readRef(V)(){
>           if(!enoughSpaceLeft(V.sizeof)) throw new Exception("1");
>           auto off=offset;
>           offset+=V.sizeof;
>           return *cast(CopyQualifiers!(T,V)*)(slice.ptr+off);
>       }
>       auto readValue(V)(){ return readRef!V(); }
> private:
>       T[] slice;
>       size_t offset=0;
> }
>
> auto binaryReader(T)(T[] slice){ return BinaryReader!T(slice); }
>
> void main(){
>       import std.stdio;
>       try{
>           auto testData = "THIS IS BINARY TEST DATA"; // no comment
>           auto stream = binaryReader(testData);
>           static assert(is(typeof(stream.readRef!uint())==immutable));
>           (ref ref_){
>               auto value = stream.readValue!uint();
>           }(stream.readRef!uint());
>       }catch(Exception e){
>           writeln("exception error: ",e.msg);
>       }catch{
>           writeln("exception unknown");
>       }
> }
>
>

seems to be a good start - how would you implement such slice/reader thing in idiomatic D style - the same?