www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array of const objects with indirections and std.algorithm.copy

reply drug <drug2004 bk.ru> writes:
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
Jul 27 2016
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jul 27 2016
parent drug <drug2004 bk.ru> writes:
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?
Jul 28 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jul 28 2016
parent drug007 <drug2004 bk.ru> writes:
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
Jul 28 2016