On Friday, 26 July 2024 at 10:04:45 UTC, Jonathan M Davis wrote:
On Friday, July 26, 2024 2:17:21 AM MDT Dom DiSc via Digitalmars-d-learn wrote:
If you are not able to construct a mutable copy of a type, why on earth are you handing it over by value?!?

Why not?

Because you can't make a mutable copy?

Structs are [...] often pseudo-reference types. [...]
such types can often work just fine with const copies, because the data that's shared between objects is const or immutable.

Then declare the template to take a const parameter.

```d
immutable MyNonCopyableType x;
MyNonCopyableType y = x; // compile error?
```

If you can't get a mutable copy of MyNonCopyableType, then yes, you'll get a compiler error.

This is why you should get the same error, if the compiler cannot create a mutable parameter-by-value copy.

In D, const is pretty much cancer, honestly. You do _not_ want to use it for generic code if you can possible avoid it,

Why? In a template that guarantees not to modify a parameter by declaring it const, what bad can happen?

because many, many types do not work with it at all.

At least reading it should never be a problem. And nothing more one want to do with a const parameter.

But I don't see your problem. I'm taking about situations where a const instance of a type IS ALREADY THERE (which will never be the case with any of your problematic types), and I want to have a mutable copy of them. So if the compiler would discard the const from parameters that are anyway never const, that's a NOP. All is fine.

On the other hand if there is a const object, that should be an object of a type that indeed CAN provide mutable copies. This is also fine.

So, where is the problem if the compiler drops "const" from the by-value copy of a parameter?

in situations where a type can be logically const (or which could be const in C++), it cannot be const in D, because D's const is simply too restrictive.

Sorry, but if a type is "logically const" (like a range) and you read it and thereby change it's internal state, then the template that guaranteed not to modify a parameter is very likely to destroy this internal state, and so you are much better of if this doesn't compile beforehand.

Some templates are simply not meant to work with all kinds of user defined types.

If you declare the parameter to be const, then there are a lot of types that won't work with the template.

Fine. If I can change the internal state via read-functions, I don't want to work with that bogous type. If my intention is not to modify an object, I'm perfectly ok that I can't use may of that fake-const types functions.

On top of that, in many cases, getting a mutable copy would give you completely incorrect behavior - e.g. if a range is a range over a container, you need that range to point to the elements in the container, and if the range refers to those elements as const, then getting a mutable copy of those elements would mean that they're no longer necessarily the same elements which are in the container (they might be at the point that the copy is made, but that won't necessarily stay true, whereas it would if the elements aren't copied).

Ranges are a bad example, because they really cannot be const. They are completely unusable in a function not modifying them, because reading them is using them up. So a function taking a range as parameter indeed cannot guarantee not to modify it (at least not if it reads that parameters data at all).

It's also the case that a lot of code simply avoids using const altogether with user-defined types

Fine. Then you won't run into the problem I have. And indeed, as you weren't aware of this problem is an indicator that you are not really using const.

Most anyone who tries to use D's const like you would in C++ eventually stops, because D's const is simply too different from C++'s const for that to work.

No, so far the C++ code I converted to D is working fine. And it is heavily using const - but it uses it correct, despite C++ doesn't enforce that. Maybe I never used C++ the way it was meant?!?

And that's especially true with templated code, since if it has to work with a large range of types, types which don't work with const are going to be on the list.

Nope. Constraints work very good in guaranteeing that such types are NOT on the list of types the template is working with.

On top of that, some common D idioms (e.g. ranges) can't work with const, because they require mutation (a range can have const elements, but the range itself cannot be const).

Jup. If a template takes a range, it should not take it const.
But I also won't take a range by value. As whatever I do will modify the range, why should I pretend to work on a copy of it? Take it by ref!

Reply via email to