3

One of the nicer features of Rust is explicitly showing whether parameters are mutable, non-mutable, or moved from the caller's site:

foobar(&mut foo, &bar,         baz);
//     ^ mutable ^ non-mutable ^ moved (copied if trivial)

In C++ we already have tools to do this:

foobar(std::ref(foo), std::as_const(bar), std::move(baz));

Yet, though std::move is standard practice, I've never seen std::as_const being used in a function call.

Is there a reason for this, other than maybe std::as_const is too verbose? Would adding simpler syntactic sugar for it provide a good new feature that makes C++ more readable?

cigien
  • 57,834
  • 11
  • 73
  • 112
Kostas
  • 4,061
  • 1
  • 14
  • 32
  • Because parameters are passed by value, no sense to mark value to be const, if it's going to be copied anyway. – KamilCuk Dec 23 '20 at 17:02
  • Isn't readability reason enough? You can't know whether it's passed by value or reference from the caller's perspective. I love C++, but I'm still annoyed I have to look up the declaration of a function any time I see it in code to understand if/how it's modifying arguments. – Kostas Dec 23 '20 at 17:04
  • `can't know whether it's passed by value or reference from the caller's perspective` You do know because you know function prototype. – KamilCuk Dec 23 '20 at 17:05
  • @Kostas Whether or not an argument will be changed is a property of the function, not of the call site. It doesn't help for the caller to specify it. – François Andrieux Dec 23 '20 at 17:06
  • Having (only) `const` be explicit is noways considered an anti-pattern, e.g. lambda's `operator()` being `const` by implicit default and `mutable` only on explicit request. `foobar(foo)` not modifying `foo` could be considered the _safe_ default. – dyp Dec 23 '20 at 17:06
  • @Kostas You should be looking up the functions you use _anyway_, if you don't already know what they do. It's not a great hardship. – Asteroids With Wings Dec 23 '20 at 17:14
  • @dyp. That makes a lot of sense. It's funny though how this is the case for a language that is as imperative as it gets. – Kostas Dec 23 '20 at 17:17
  • 3
    I don't know Rust very well, but I would think it's focus on `&foo` vs `&mut foo` vs `foo` is also important for borrowing: It prevents you from handing out two mutable references, for example - which is why having `mut` explicit is quite important. Similarly, there are lifetime restrictions on `&` (without `mut`). None of that applies to C++, where `T const&` vs `T` is mostly seen as an optimization (most of the time). – dyp Dec 23 '20 at 17:22
  • 1
    That said, I would still say there's benefit from redundancy. Like _not using `auto x = foobar()`_ but instead `Integer x = foobar();` or `int x{ foobar() };`. It would require a lot of extra effort though, to get something like `foobar(mut(foo), con(bar), move(baz))` where _the compiler actually enforces using these annotations_. – dyp Dec 23 '20 at 17:25
  • 1
    @Kostas _"a language that is as imperative as it gets"_ Except... it isn't. Even just the use of functions makes it procedural, not imperative. Beyond that C++ is multi-paradigm. – Asteroids With Wings Dec 23 '20 at 17:29
  • @AsteroidsWithWings But... procedural is a subset of imperative. – Kostas Dec 23 '20 at 17:30
  • @dyp I think that makes sense. C++ is a language that doesn't really like to enforce things, and for this to have a reasonable shot to be successful there should be enforcement. It would still be nice to get some nice syntax to do this if one wants. Something like `foobar(foo&, bar const&, foobar&&)`. – Kostas Dec 23 '20 at 17:36
  • @Kostas But... lol no it isn't. – Asteroids With Wings Dec 23 '20 at 17:49
  • 1
    I agree with the readability, I've tried using `std::ref` where things could change, though what really is needed ain't extra syntax, it's a good IDE that shows the right info to you as you can't update all the legacy code – JVApen Dec 23 '20 at 18:00
  • You could cobble something together for C++, but it would not satisfy. The bottom line is such code would be non-idiomatic C++, and the syntax would be awkward to use at the callsite, and it still wouldn't do what Rust does. Because C++ just does not have the strong ownership model that Rust enforces at compile time. And C++ does not have *type state* language feature which is the secret sauce that makes the strong ownership model work. – Eljay Dec 23 '20 at 18:01
  • 1
    I've added back the Rust tag. I think it's appropriate for this question, since the OP is asking for a comparison between features of that language and C++. – cigien Dec 23 '20 at 18:20
  • @JVApen That's actually a great idea. I'll use this from now on when planning to change an argument. – Kostas Dec 23 '20 at 18:23
  • 2
    @cigien in that case, the OP should **describe the Rust behavior** to make the question more broadly applicable (which they already have, IMO). [tag:rust] is inappropriate because the question is not about Rust. I also disagree that they are asking for a comparison. They are apparently asking why no one uses the existing C++ features that they've identified as an analog to the Rust features. – Shepmaster Dec 23 '20 at 18:26
  • 1
    @Eljay note that Rust [doesn't _really_ have type state either](https://stackoverflow.com/q/3210025/155423), not since before Rust 1.0. – Shepmaster Dec 23 '20 at 18:30
  • 1
    @Shepmaster I agree that the OP is primarily asking about how something works in C++. However they have identified a feature of Rust that they believe is related. Whether it's related or not, I think users who know Rust will be able to contribute to this question, even if it's only to point out that the analogy is inappropriate. Adding the language tag is a great way of making the question visible to those users. – cigien Dec 23 '20 at 18:35
  • 2
    @cigien *to point out that the analogy is inappropriate* — but that doesn't matter here :-) The OP could have just as easily made up a fake language that had the behavior they wanted and said "how do I get this behavior in C++?". The first sentence could be changed to "I want to show whether parameters are mutable, non-mutable, or moved from the caller's site:", removing all mention of Rust, and the question would still stand as well as it does now. – Shepmaster Dec 23 '20 at 18:43
  • @JVApen Regarding IDE, the woboq code browser annotates e.g. using `&`: https://code.woboq.org/llvm/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp.html#214 – dyp Dec 23 '20 at 18:43
  • Maybe not exact duplicate - but can help: https://stackoverflow.com/questions/53450366/what-do-we-need-stdas-const-for – PiotrNycz Dec 23 '20 at 18:45
  • 2
    @Shepmaster I don't disagree that the question would stand on its own without the reference to Rust. But the OP *has* referred to Rust, so it *does* matter, and I see no problem with the tag. We don't go around retagging questions just because the question *could have been asked* slightly differently, and not require some tag in that case. – cigien Dec 23 '20 at 18:55
  • @dyp really nice, now I really want it in mine. – JVApen Dec 23 '20 at 21:02
  • @JVApen [CLion provides them](https://www.jetbrains.com/help/clion/parameter-hints.html), for example. Not sure about other IDEs. – dyp Dec 24 '20 at 09:21
  • It's a good idea, in the same idea than begin/cbegin but in general, there is no problem with function calls because the return by value pattern is prefered over the non const reference one => when you have the reference pattern, you remember it easily and place the output argument in last position. And the function name should be enough explicit with a good convention like perform, apply, ... – Cevik Jan 01 '21 at 14:27

0 Answers0