Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I agree that I would have preferred destructive moves, but move semantics makes C++ a much richer and better language. I kinda think pre-move semantics, C++ didn't quite make "sense" as a systems programming language. Move semantics really tied the room together.

    const int x = f(); // this is always get evaluated at compile time, (or if it can't, then fail to compile)
That's very silly. You're saying this should fail to compile?

    void foo(int x) {
        const int y = bar(x);
    }
There's no way the compiler can run that, because it doesn't know what x is (indeed, it would have a different value every time you run the function with a new argument). So your proposal would ditch const completely except in the constexpr case, everything runtime would have to be mutable.

So you respond "well, I didn't mean THAT kind of const, you should have a different word for compile-time constants and run-time non-mutability!" Congratulations, you just invented constexpr.

There are many bad things about C++, but constexpr ain't one of them.



>There's no way the compiler can run that, because it doesn't know what x is (indeed, it would have a different value every time you run the function with a new argument). So your proposal would ditch const completely except in the constexpr case, everything runtime would have to be mutable.

Yeah, I see no problem with that. Non-constant expressions usage of 'const' has always just seemed like a waste of time for me, never found it useful. But I guess a lot of people really liking typing const and "preventing themselves from accidentally mutating a variable" (when has that ever happened?), so as a compromise I guess you can have a new keyword to force constant expressions:

  constexpr auto x = foo(); // always eval at compile time
  const auto x = foo(); // old timey const, probably runtime but maybe got constant folded.
but it's not really a big deal what they keyword is, the main point was that "give me a constant value" should be at the usage site, not at the function definition.


> the main point was that "give me a constant value" should be at the usage site, not at the function definition.

The issue is, not everything can be done at compile time, and so “I can use this at compile time” becomes part of the signature because you want to ensure that it will continue to be able to be used that way. Without it, changes in your function could easily break your callers.


Exactly right. There's a huge benefit to encode the ability for compile-time evaluation in the signature of the function itself. Much better than doing it "ad-hoc", like how template instantiation does it. Sometimes it will work, sometimes it doesn't. constexpr functions always work.


I like const because I can look at a function signature and know that nothing downstream is mutating a parameter. I can also write a function that returns a const reference to a member and know that nobody in the future will ever break my invariants.

This isn't about "oops, I didn't mean to mutate that." This is about rapidly being able to reason about the correctness of some code that is leveraging const-qualified code.


> "preventing themselves from accidentally mutating a variable" (when has that ever happened?)

I can't count the number of times I've seen someone new to the language use map::operator[] without realizing that it's a mutating operation.


It’s extra delightful that vector::operator[] isn’t mutating, so you can change a vector to a map and get rather different semantics.


map::operator[] should just be [[deprecated]] - even if you want to mutate the map it's probably not the best way to do what you want.


I kinda like it on occasion. Works like pythons defaultdict. Like, if you wanna count something:

    for (const auto &thing: collection) {
        counts[thing]++;
    }
Works nicely, you don't have to check if it's already there before ++ing it. As long as you know that's what operator[] does, it comes in handy more than I would've expected.


Yeah. It has its uses. You could accomplish the same with the rather verbose `counts.try_emplace(thing).first->second++` but nobody wants to type that (even if it is more explicit about what it's doing).

Another popular use case is something along the lines of:

    std::unique_ptr<T>& ptr = ptrs[key];
    if (ptr != nullptr) {
      ptr = std::make_unique<T>(...);
    }
That said, I don't know what behavior I'd want if maps didn't automatically insert an element when the key was absent. UB (as with vector)? Throw an exception? Report the incident to Stroustrop? All these options feel differently bad.


> when has that ever happened?

Maybe it's not a concern in C-family languages, but rust's culture of defaulting to let and only using mut when it's specifically required does feel very pleasant and ergonomic when I'm in that headspace.


> (when has that ever happened?)

to me, pretty much a few times per week at least




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: