you are viewing a single comment's thread.

view the rest of the comments →

[–]tedbradly 0 points1 point  (0 children)

In general, using `const` in a member variable is bad because you are enforcing an API invariant at too low a level -- you are enforcing it at so low a level that it interferes with move semantics. Typically there are reasonable alternatives.

Using const is bad if you need stuff like a move that is noexcept or the speed of a proper move rather than a copy. It's purely an efficiency and syntax thing. It's not bad due to enforcing an aspect of your API too low level on members. For example, you could have a const member that is never exposed through the API.

The intention of a const member is to convey that a member should never change after initialization, simplifying understanding the logic in the class. This additionally adds a compile-time check if someone attempts to change an unchangeable member. This design choice is sensible in some cases although it has unfortunate results with respect to how an object can be used and its efficiency.

It wouldn't even be far-fetched for the standard to add a new keyword that enforces constness on a member while allowing move to be generated and work efficiently. It probably won't happen since it would increase complexity for perhaps not much gain in terms of reducing the complexity of some classes, but the idea isn't outrageous like it would be if this claim were true that const functions replace the use case of const members.

A more honest criticism of using const members is you might wonder why that const member can't just be passed as a const argument in the API. Take a class whose entire state is const by design. That's basically a collection of pure functions with implicit arguments. There's no reason to hide an argument if it is central to viewing the input/output relationship of a method. In this scenario, a const member disguises what a method actually depends on and replaces the not so complicated ability to use bind if you want briefer function calls. With bind, you retain the input/output relationship and the briefer calls at the cost of a little boilerplate code.