Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]

2018-03-15 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 15 March 2018 at 15:41:54 UTC, Robert-D wrote:
Why something like this doesn't compile (with or without the 
cast on bb.dup)?


struct S {
string[string] aa;

S dup() inout pure {
return S(cast(string[string]) aa.dup);
}
}

struct SS {
S[] bb;

SS dup() inout pure {
return SS(cast(S[]) bb.dup);
}
}

Or:

const(S)[] ss = [S(["": ""])];
S[] d = ss.dup;


For this to work, the standard .dup function would need to call 
.dup on each element of the array. Since this may or may not be 
what the programmer wants, the standard library doesn't do it for 
you. Generally, this is called deep-duping, or deep cloning. We 
can implement our own deepdup function:


struct S {
string[string] aa;

S dup() const {
return S(aa.deepDup);
}
}

struct SS {
S[] bb;

SS dup() const {
return SS(cast(S[])bb.deepDup);
}
}

import std.traits : Unqual, isArray, isAssociativeArray;

auto deepDup(T)(T obj)
if (!isArray!T && !isAssociativeArray!T)
{
static if (is(typeof(obj.deepDup))) {
return obj.deepDup;
} else static if (is(typeof(obj.dup))) {
return obj.dup;
} else static if (is(typeof({ Unqual!T tmp = obj; }))) {
return obj;
} else {
static assert(false, "Can't deepDup a "~T.stringof);
}
}

auto deepDup(T)(T[] arr) {
Unqual!T[] result;
result.reserve(arr.length);

foreach (e; arr) {
result ~= e.deepDup;
}

return result;
}

auto deepDup(T : V[K], K, V)(T aa) {
alias UV = Unqual!V;
alias UK = Unqual!K;
UV[UK] result;

foreach (k, v; aa) {
UK kdup = k.deepDup;
UV vdup = v.deepDup;

result[kdup] = vdup;
}

return result;
}

--
  Simen


Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]

2018-03-15 Thread Robert-D via Digitalmars-d-learn

On Thursday, 15 March 2018 at 13:18:38 UTC, Simen Kjærås wrote:

On Thursday, 15 March 2018 at 12:00:08 UTC, Robert-D wrote:
I want the function to create a mutable copy from a const or a 
imutable


Like this:

void main() {
const S s = S(["": ""]);
S b = s.dup();
}

How can i do that?


In that case, the problem is that you also have to .dup the aa:

S dup() const pure {
return S(aa.dup);
}

However, it seems aa.dup returns the wrong type - one would 
expect V[K] for inout(V[K]), but it returns inout(V)[K], or 
inout(string)[string], in your case. That's apparently a known 
bug: https://issues.dlang.org/show_bug.cgi?id=14148.


The solution for now, then, is this:

S dup() const pure {
return S(cast(string[string])aa.dup);
}

--
  Simen


Why something like this doesn't compile (with or without the cast 
on bb.dup)?


struct S {
string[string] aa;

S dup() inout pure {
return S(cast(string[string]) aa.dup);
}
}

struct SS {
S[] bb;

SS dup() inout pure {
return SS(cast(S[]) bb.dup);
}
}


Error: static assert: "Cannot implicitly convert type inout(S) to 
S in dup."


Or:

const(S)[] ss = [S(["": ""])];
S[] d = ss.dup;

Error: template object.dup cannot deduce function from argument 
types !()(const(S)[]), candidates are:
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2086):  
  object.dup(T : V[K], K, V)(T aa)
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2122):  
  object.dup(T : V[K], K, V)(T* aa)
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4191):  
  object.dup(T)(T[] a) if (!is(const(T) : T))
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4207):  
  object.dup(T)(const(T)[] a) if (is(const(T) : T))





Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]

2018-03-15 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 15 March 2018 at 12:00:08 UTC, Robert-D wrote:
I want the function to create a mutable copy from a const or a 
imutable


Like this:

void main() {
const S s = S(["": ""]);
S b = s.dup();
}

How can i do that?


In that case, the problem is that you also have to .dup the aa:

S dup() const pure {
return S(aa.dup);
}

However, it seems aa.dup returns the wrong type - one would 
expect V[K] for inout(V[K]), but it returns inout(V)[K], or 
inout(string)[string], in your case. That's apparently a known 
bug: https://issues.dlang.org/show_bug.cgi?id=14148.


The solution for now, then, is this:

S dup() const pure {
return S(cast(string[string])aa.dup);
}

--
  Simen


Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]

2018-03-15 Thread Robert-D via Digitalmars-d-learn

On Thursday, 15 March 2018 at 11:33:49 UTC, Simen Kjærås wrote:

On Thursday, 15 March 2018 at 11:18:48 UTC, Robert-D wrote:

[...]



This is where things go wrong:

[...]


'inout' means that this function can keep the const, immutable 
or mutable status of the type on which the function is called. 
This means that an inout function has to treat the object as 
const, because otherwise the function would break the 
guarantees of immutable and const.


When using inout on a function, you always want to put inout on 
something else too - either a ref parameter or the return 
value. In your case, this works:


inout(S) dup() inout pure {
return inout(S)(aa);
}

--
  Simen


I want the function to create a mutable copy from a const or a 
imutable


Like this:

void main() {
const S s = S(["": ""]);
S b = s.dup();
}

How can i do that?


Re: Error: cannot implicitly convert expression this.aa of type inout(string[string]) to string[string]

2018-03-15 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 15 March 2018 at 11:18:48 UTC, Robert-D wrote:

struct S {
string[string] aa;

S dup() inout pure {
return S(aa);
}
}

void main() {
auto s = S(["": ""]);
s.dup();
}

Result:
 Error: cannot implicitly convert expression this.aa of type 
inout(string[string]) to string[string]



I need help with the above program.



This is where things go wrong:

S dup() inout pure {


'inout' means that this function can keep the const, immutable or 
mutable status of the type on which the function is called. This 
means that an inout function has to treat the object as const, 
because otherwise the function would break the guarantees of 
immutable and const.


When using inout on a function, you always want to put inout on 
something else too - either a ref parameter or the return value. 
In your case, this works:


inout(S) dup() inout pure {
return inout(S)(aa);
}

--
  Simen