copy must be const?!?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Jul 25 13:07:03 UTC 2024


On Thursday, July 25, 2024 6:00:58 AM MDT Dom DiSc via Digitalmars-d-learn 
wrote:
> > And no, in general, you don't want to be casting away const or
> > immutable. There are cases where it can work (e.g. if the cast
> > does a copy, which it would with an integer type)
>
> But a parameter given by value is ALWAYS a copy.
> So if a copy is done, the copy should be mutable. I can't see why
> that should ever be a problem. The compiler should never create
> new values const or immutable unless explicitly advised to do so.

It has to be a _full_, independent copy. If you're talking about integer
types, that's a non-issue, but if you're talking about types with any
indirections, it becomes a big issue. If the type contains any pointers,
dynamic arrays, class references, etc. then the copy can't be mutable unless
you're dealing with a struct with a copy constructor that does a deep copy
of all of the member variables. So, in the general case, you cannot copy a
value and expect to get a mutable result.

> E.g.
> ```d
> void fun(myType x) { }
> ```
>
> called with immutable object should create a mutable x, because
>
> ```d
>    myType x = immutableObject;
> ```
>
> will also create a mutable x. If I want an immutable x, i can do
>
> ```d
>    immutable myType = immutableObject;
> ```
>
> ```d
> void fun(T)(T x) if (is(Unqual!T==myType)) { }
> ```
>
> should also create a mutable x, for the same reason, because if I
> want an immutable x, I can do
>
>
> ```d
> void fun(T)(immutable(T) x) if (is(Unqual!T==myType)) { }
> ```
>
> Therefore I consider the current behaviour a bug.

It's most definitely not a bug that IFTI (Implicit Function Template
Instantiation) instantiates the template with the exact type that it's
given. In the general case, that's what you want - particularly since many,
many types (probably the vast majority of types) cannot be const or
immutable and then result in a mutable copy when they're copied. That really
only works with very simple types with no indirections. In the general case,
there is no expectation whatsoever that it's going to be possible to get a
mutable copy from a const or immutable variable, and generic code that
expects that to work is very likely to run into problems very quickly.

Now, the fact that code such as

    void fun(T : const U, U)(U x)
        if(is(immutable T == immutable U))
    {
        ...
    }

or code like

    void fun(T)(Unqual!T x)
    {
    }

doesn't work with IFTI and requires explicit instantation is definitely a
deficiency in IFTI's current capabilities, but in the general case, we very
much want

    void fun(T)(T x) {}

to be instantiated as fun!(const Foo) if it's passed a const Foo.

For some types, we _would_ like the ability to tell the compiler to
implicitly instantiate function templates with a tail-const version similar
to what we get with dynamic arrays, but that really only makes sense for
certain types such as ranges.

But either way, it would cause quite a few problems if IFTI started
instantiating templates in general with mutable instead of the actual type
that it's given, because it's extremely common that const and immutable
types cannot be converted to mutable.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list