Thread overview
Array of const objects with indirections and std.algorithm.copy
Jul 27, 2016
drug
Jul 27, 2016
Ali Çehreli
Jul 28, 2016
drug
Jul 28, 2016
Ali Çehreli
Jul 28, 2016
drug007
July 27, 2016
I have the following:

```
struct Foo
{
	int[] i;
	
	this(int[] i)
	{
		this.i = i.dup;
	}
	
	ref Foo opAssign(ref const(this) other)
	{
		i = other.i.dup;
		
		return this;
	}
}

const(Foo)[] cfoo;
```

I need to copy it:

```
Foo[] foo;

cfoo.copy(foo); // fails to compile because phobos in case of array uses
                // array specialization and this specialization fails
                // see https://github.com/dlang/phobos/blob/v2.071.1/std/algorithm/mutation.d#L333
```

but it works:
```
foreach(ref src, ref dest; lockstep(cfoo, foo))
		dest = src;
```

In my opinion the possible decision is disabling the array specialization if the arrays can't be low-level copied. And the question raises here - why `areCopyCompatibleArrays` doesn't work in this case? I found that
```
	// return true
	pragma(msg, __traits(compiles, { typeof(foo).init[] = typeof(cfoo).init[]; } ))
	// return false
	pragma(msg, __traits(compiles, { foo[] = cfoo[]; } ))
```
The question is - shouldn't `areCopyCompatibleArrays` be modified according code above to use array specialization where it is appropriate and allow to copy arrays by elements when it is needed?

The full code is here https://dpaste.dzfl.pl/5e13e183a006
July 27, 2016
On 07/27/2016 04:51 AM, drug wrote:
> I have the following:
>
> ```
> struct Foo
> {
>     int[] i;
>
>     this(int[] i)
>     {
>         this.i = i.dup;
>     }
>
>     ref Foo opAssign(ref const(this) other)
>     {
>         i = other.i.dup;
>
>         return this;
>     }
> }

You're defining the assignment from const to non-const. It could have relied on .dup or something else. The compiler cannot know the equivalent for the copy operation.

> const(Foo)[] cfoo;
> ```
>
> I need to copy it:
>
> ```
> Foo[] foo;
>
> cfoo.copy(foo); // fails to compile because phobos in case of array uses
>                 // array specialization and this specialization fails
>                 // see

That makes sense to me. Otherwise we wouldn't be observing const-ness of the elements: Mutate the original through the copy...

> https://github.com/dlang/phobos/blob/v2.071.1/std/algorithm/mutation.d#L333
> ```
>
> but it works:
> ```
> foreach(ref src, ref dest; lockstep(cfoo, foo))
>         dest = src;

Because the programmer said it's safe to do so. :)

>     // return true
>     pragma(msg, __traits(compiles, { typeof(foo).init[] =
> typeof(cfoo).init[]; } ))

(Unrelated, I've just learned that pragma() does not require a semicolon. Ok... :) )

Well, that's interesting. I guess it means null = null, which does not compile. I think it's a bug that the above produces true.

However, I would write that __traits(compiles) in a more straightforward way. (You're creating a lambda there, which does not have anything to do with the core of the problem here.) So, the following produces false, false:

    pragma(msg, __traits(compiles, [ typeof(foo)() ] = [ typeof(cfoo)() ]));
    pragma(msg, __traits(compiles, foo = cfoo));

Yeah, those look more straightforward to me at least for this problem.

Ali

July 28, 2016
I see. I'll try to rephrase my question to be clear. We have:
```
struct Foo
{
	int i;
	float f;
}

int main()
{
	const(Foo)[] cfoo = [Foo(1, 0.5), Foo(2, 0.75)];
	Foo[] foo;

	cfoo.copy(foo); // it works, constness no matter here because Foo is value type
}
```
but if Foo contains indirections it won't be a value type anymore and `copy` doesn't work. It's right and expected. Then I define `opAssign` to accept a const instance of `Foo` and I expect that `copy` should work because `Foo` (with indirections) now can be safely copied using `opAssign`. But it doesn't work just because current implementaion of `copy` assumes that if its arguments are array then it can be low-level copied. But `cfoo` is array of element that can't be bitblt-ed and should be copied by element. `copy` does by element copying for ranges, but not for arrays.
Am I wrong or copy array specialization should be extended to support arrays that require by element copying?
July 28, 2016
On 07/27/2016 04:51 AM, drug wrote:

> cfoo.copy(foo); // fails to compile because phobos in case of array uses
>                 // array specialization and this specialization fails
>                 // see
> https://github.com/dlang/phobos/blob/v2.071.1/std/algorithm/mutation.d#L333

Thanks for explaining further. Yes, this is a bug. Although areCopyCompatibleArrays!(const(Foo)[], Foo[]) is true, std.algorithm.copy of that specialization fails. Please create a bug report at

  https://issues.dlang.org/

Thank you,
Ali

July 28, 2016
On 28.07.2016 21:45, Ali Çehreli wrote:
> On 07/27/2016 04:51 AM, drug wrote:
>
>  > cfoo.copy(foo); // fails to compile because phobos in case of array uses
>  >                 // array specialization and this specialization fails
>  >                 // see
>  >
> https://github.com/dlang/phobos/blob/v2.071.1/std/algorithm/mutation.d#L333
>
> Thanks for explaining further. Yes, this is a bug. Although
> areCopyCompatibleArrays!(const(Foo)[], Foo[]) is true,
> std.algorithm.copy of that specialization fails. Please create a bug
> report at
>
>    https://issues.dlang.org/
>
> Thank you,
> Ali
>
Thank you too.
done https://issues.dlang.org/show_bug.cgi?id=16332