6 ms·
I don't really understand what you're saying. 'const' in C and C++ is broken. Not only is it like a Chinese word that varies wildly in meaning depending on whe
by CountSessine 11y ago
I don't really understand what you're saying.
'const' in C and C++ is broken. Not only is it like a Chinese word that varies wildly in meaning depending on where you use it and how it is inflected, but in C-family languages, 'const' modifies type, making objects that benefit from the compiler hints 'const' implies type-incompatible with objects that do not.
They're not type-incompatible in any way that doesn't violate those compiler hints in the first place - C and C++ fully support sensible coercion between const and non-const types. What more do you want?
This results in the problem of some know-it-all deciding that a core API needs to be const-correct, and checks in changes making it so, only to find that the entire fucking code base is now broken
Would you rather it compiled and silently broke? If some dingus breaks the build by changing an API without checking in the corresponding code using the API, how is that C/C++'s fault?
By contrast, languages such as Ada have explicit and implicit constantness restrictions ('in' parameters, for instance, cannot be modified), but these do not modify the type of the object, allowing objects with these restrictions to be type-compatible with objects without them.
This is bizarre. Can you take that 'in' parameter and then pass it on to another function as an 'in/out' parameter? If so, then either
1. Ada just made you a copy silently (bad)
2. Ada is broken and 'in' means nothing (worse).
If neither of those are true and an 'in' can't be transitively passed on as an 'in/out', then that's a type - however you want to refer to it, 'in' is then a type with all of the 'broken' type restrictions you're railing against in C/C++.
- thisisnotatest 11y agoconst is type-incompatible like this: Suppose you want to write a function that returns all the nodes in a tree that satisfy some property. In C++ you have to define two different versions (or use templates to make the compiler clone it for you): vector<Node*> GetGoodNodes(Node* root); vector<const Node*> GetGoodNodes(const Node* root); If more than one type is involved in the operation, there can be a combinatorial explosion.
- golergka 11y agoI don't feel that I understand purpose of this function yet. Does this function return data point that it creates itself, or does it retrieve these nodes from somewhere else? If it's the first option, who's in charge of deleting them? If it's a second option, who's in charge of counting references to these objects? Also, if it's a second option, and this data points are retrieved from a certain storage, are you absolutely sure that whoever gets this data should be able to modify them?
- SamReidHughes 11y ago> Does this function return data point that it creates itself, or does it retrieve these nodes from somewhere else? It returns pointers to the nodes in the tree. You know this because the caller isn't supposed to (or allowed to) delete them, because if the caller was responsible for that, they'd be wrapped in smart pointers. > If it's a second option, who's in charge of counting references to these objects? The pointers in the return value are valid as long as their particular descendant of the function parameter isn't deleted. There's no need for reference counts, and if they're present at all, they aren't updated by this function, since the caller isn't responsible for decrementing them. If the caller was responsible, the return value would be a vector of smart pointers. > Also, if it's a second option, and this data points are retrieved from a certain storage, are you absolutely sure that whoever gets this data should be able to modify them? If they have a const node *, they shouldn't. If they don't, they should.
- golergka 11y agoThanks! Your first two answers would be obvious if we assume that we're working with modern codebase written by adequate developers, but that's a very strong assumption to make, so I wanted to be specific. And your final answer is, well, exactly the point I was trying to steer the conversation to. In other words, if you declare both methods, it means that you're doing something wrong: you're giving away data mutably and immutably at the same time, and it just doesn't make sense.
- SamReidHughes 11y ago
- kybernetyk 11y agoYes, and what's wrong with that? You certainly don't want someone from the outside altering the nodes directly if you have an API which should be used instead. Whenever I need to return a non-const reference/pointer to some inner data (which is not often) I name the method "mutableFoo()" to make clear what you're getting. But most of the time (provided a sane API design) you won't have that problem anyway.
- bitwize 11y agoFirst of all, Ada may have already made a copy of the value; small (register-sized) values tend to be passed by copy into subprograms. If 'in' is a type than so is the concept of an lvalue in C and C++ -- because constants (and 'in' parameters which function as constants with local scope) in Ada are not lvalues; they cannot be assigned to by the semantics of the language. (In C and C++, every sense of 'const' can be gotten around; even const methods can mutate object instance variables by const_casting this.) You can call any constraint imposed by the language a type and that may be true in the abstract sense, but what counts when talking about types in a language is what the language's own type system has to say on the matter. Parameter modes (in, out, in out) form a part of the type of the subprogram (procedure or function) the parameter is a part of, but constantness is not a part of the type of the value in Ada. Note that this is not the only way types differ in Ada than in C++ when it comes to access: C++ types encode information about how a parameter is passed, Ada types do not. The Ada declaration: procedure Foo(I : in Integer); may be equivalent to C++ void foo(int i); or void foo(const int& i); depending on how the compiler chooses to pass the values. Note that even 'in out' parameters may be passed by value through a 'pass by copy-in copy-out' mechanism, so whether a parameter is passed by value or reference is largely handled behind the scenes, so the type system doesn't include that information. If it did, Ada would be even more verbose and unwieldy than its reputation suggests, as type enforcement is much more strict in Ada.
- CountSessine 11y agoYou can call any constraint imposed by the language a type and that may be true in the abstract sense, but what counts when talking about types in a language is what the language's own type system has to say on the matter What counts isn't so much what the specification calls a 'type' but rather how the compiler does type reduction - and with all of the compilers I've worked with, argument decorators like 'in' & 'out' are typically handled during type reduction. depending on how the compiler chooses to pass the values. Note that even 'in out' parameters may be passed by value through a 'pass by copy-in copy-out' mechanism, so whether a parameter is passed by value or reference is largely handled behind the scenes, so the type system doesn't include that information. If it did, Ada would be even more verbose and unwieldy than its reputation suggests, as type enforcement is much more strict in Ada. Very interesting! I know very little about Ada - other than that it has generally been considered as a safer alternative to C for applications-programming in the aerospace software world. At the same time, I can say that without the ability to determine the how of how the compiler will pass arguments - by value, by copy, by reverse copy, by reference - I wouldn't consider Ada to be an alternative to C in the systems-programming domain, any more than I would consider Haskell or Javascript to be systems-programming languages. Your original claim, in your words, was that 'const' in C and C++ is broken. C, or any other systems-programming language, simply has more constraints on what const could possibly be. The Ada approach to handling const would simply never work in C with C's implementation guarantees. To pseudo-quote a great man, Dennis Ritchie, If you want magical argument passing, sometimes resulting in silent and unexpected argument copying, you know where to get it.