Thread overview
Why can't I copy a const struct?
Nov 15, 2013
Atila Neves
Nov 15, 2013
Ali Çehreli
Nov 15, 2013
Ali Çehreli
Nov 16, 2013
Atila Neves
November 15, 2013
    private struct DummyStruct {
        int[] a;

        this(this) {
            a = a.dup;
        }
    }


    void main() {
        const dummy1 = DummyStruct();
        DummyStruct dummy2 = dummy1;
    }

    struct_copy.d(12): Error: conversion error from const(DummyStruct) to DummyStruct

Surely I should be able to copy it and use the mutable version as I please, no? I'd understand if the postblit constructor wasn't defined...

Atila
November 15, 2013
The short answer to the question in the subject line is because D does not have copy constructors.

On 11/15/2013 07:12 AM, Atila Neves wrote:

>      private struct DummyStruct {
>          int[] a;
>
>          this(this) {
>              a = a.dup;

That line can work only if a is mutable. The trouble is, the type of a is const(int[]) there.

>          }
>      }
>
>
>      void main() {
>          const dummy1 = DummyStruct();
>          DummyStruct dummy2 = dummy1;
>      }
>
>      struct_copy.d(12): Error: conversion error from const(DummyStruct)
> to DummyStruct
>
> Surely I should be able to copy it and use the mutable version as I
> please, no? I'd understand if the postblit constructor wasn't defined...

That makes sense but the compiler would not analyze the code and ensure that the code obeys const. (It probably can in most situations though.)

> Atila

One workaround is a constructor that takes by ref const:

import std.stdio;

private struct DummyStruct {
    int[] a;

    this (int[] a) {
        this.a = a.dup;
    }

    this(ref const(DummyStruct) that) {
        writeln("copy");
        this.a = that.a.dup;
    }
}

void main() {
    const dummy1 = DummyStruct([ 1 ]);
    auto dummy2 = DummyStruct(dummy1);  // <-- note different syntax
    assert(dummy2.a.ptr != dummy1.a.ptr);
}

Ali

November 15, 2013
On 11/15/2013 10:37 AM, Ali Çehreli wrote:

>  >          this(this) {
>  >              a = a.dup;
>
> That line can work only if a is mutable. The trouble is, the type of a
> is const(int[]) there.

I lied! :) The type of a is int[] in there. The actual trouble is, to be able to start executing this(this), the left-hand side a should have already been a reference to the right-hand side a.

What fails is that initialization of the mutable reference on the left-hand side from the const reference on the right-hand side.

Ali

November 16, 2013
> What fails is that initialization of the mutable reference on the left-hand side from the const reference on the right-hand side.
>
> Ali

Ah, right. In D a copy is a move followed by a post-blit and the move fails because the source is const, got it.

It's still silly, though. In theory the compiler could check the postblit constructor to see if it copies (I'm aware this might be easier said than done).
In my case it'll mean that I'll have to drop const off of some methods because of this. And they really should be const...

I hate to say it, but this is where const_cast would take care of the problem for me in C++.