A Question of Const

A reader, J. Daniel Smith, inquiries

 

You wrote “The absence of const support in the base class library… “;

 

Can you elaborate any on what the plans are for “const” as they relate to C++/CLI and C#?

 

I know “const” can open up a whole can of worms about all the various semantics of “const”. And some uses of “const” such as “const std::string& amp”; to avoid making a copy aren't needed with managed code.

There are a number of issues, of course, with the const modifier, as you point out. It is used in at least three ways: (a) to indicate that an object is read-only, (b) to indicate that a parameter is being passed by reference only for the sake of efficiency and not because it will be modified as a side-effect of the method call – this is your const example in your third sentence, and (c) to indicate that a class method does not, as a side-effect of its invocation, modify any of the non-static class members.

There is no entry for constant in the index of Jim Miller’s Common Language Infrastructure Annotated Standard, and there is no const modifiers on the Base Class Library API. This presents a problem for C++ if it wishes to present support for (b) and/or (c) within managed code. The choice made, which I argued against with the effectiveness of Don Quixote doing battle with his windmills, is to provide full support for (b), so that one can specify a const modifier to any parameter of a method.

Designs in many cases are a series of accidents, and reflect non-conscious biases of its participants. I believe this design choice, for example, reflects the cyclopean vision of native C++ rather than an balanced Janus vision looking out at both the native and managed paradigms. Here are the problems that I see from the point of a .NET programmer.

(1) it is not enforceable on any parameter subsequently passed to a Base Class Library method. Therefore it is not possible to insure the transitive closure on the constness of the call chain for each parameter. This is both the benefit and the `can of worms’ in using const parameters – the compiler can detect a break in the transitive closure of the call chain that we ourselves are for the most part clueless. [I say this is a `can of worms’ because it is really really difficult to backpatch const parameters once the application is over some threshold of complexity. Either you build it into your application from the start or else it is a grim imposition and, like dealing with template instantiation, is an example of where the language becomes an impediment rather than aid.] As with most things, there are two levels of discourse about const – the what you should do in principle level and what you do in practice. My gut feeling is that a majority of C++ applications do not use const well, but I have no real data and base this on informal conversations with students when I use to teach the language.

(2) in order to pass a const parameter to a Base Class Library method, one must cast away the constness of that parameter at each point of call, or create a local non-const entity. If you don’t, the compiler [I’m told] will flag the call as illegal since the Base Class Library method does not of course provide a const parameter. This is problematic for a number of reasons:

(a) const_cast is not permitted on all reference types, I believe, although I could be wrong, and a safe_cast of a reference type results in a run-time check that is expensive – static_cast is permitted but I am not sure whether it allows the casting away of const. The problem here is that this is very complicated and is not the level a serious programmer wishes to bend his or her attention to. It is error-prone and grim, imo.

(b) Casts are morally indefensible to many coding standards and project norms. They are often characterized as second-class citizens resorted to by programmers of dubious character, and can easily result in the greatest of managed sins: unverifiable code. And yet in order to make use of the Base Class Library, all const parameters must [the programmer has no choice] be cast away.

(c) The only real solution to this is to not use the const mechanism for parameters, which solves (a) and (b) and (1), but puts in question the value of our support for the feature to begin with.

While these criticisms of the C++/CLI design choice regarding const are plausible, they may prove as insignificant as their reception. Their warrant rests on two axioms: (1) use of the Base Class Library is fundamental to .NET programming, and (2) use of C++/CLI will shift from interoperability between the two paradigms, which is apparently the primary use of the current language design, to the dynamic paradigm itself. The question then is, if and when that happens, will the use of C++/CLI be a first class experience? We don’t know the answer to that because as yet we have no practicable experience with the language and, I would argue, no real empathy as yet with the paradigm.

Historically, the design and implementation of C++ in its infancy addressed many of its concerns to the needs of the C community. this pointer placement is a trivial but interesting example of this. In the original implementation, it was placed at the end of the class in order to accommodate the pattern of inheriting from a struct. At the point in time when Microsoft entered into the C++ arena, C-coddling was no longer the focus, and so we placed the this pointer at the beginning of the class object, which is more efficient for pure OO designs. At the language level, the language originally supported old-style function prototypes, took out nested types, and permitted implicit calls of methods signifying a return value of int and a variable argument list. One by one, these original compromises were taken from their home and never seen again. I believe it is fair to say that the design focus of C++/CLI is also in its infancy.