www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why can't I copy a const struct?

reply "Atila Neves" <atila.neves gmail.com> writes:
     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
Nov 15 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Nov 15 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Nov 15 2013
parent "Atila Neves" <atila.neves gmail.com> writes:
 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++.
Nov 16 2013