So, I realize that const T&
and T const&
are identical and both mean a reference to a const T. In both cases, the reference is also constan
If the const
and &
get far apart, as in
krog::FlamBlott<std::map<HurkleKey,Spleen<int>>
speckleFlams( const krog::Floonage & floon, const std::map<krog::HackleSpoon,std::vector<krog::HeckleObservation<OBSN>>> & obsmap);
krog::FlamFinagleReport
finagleFlams( const krog::Floonage & floon, std::map<krog::HackleSpoon,std::vector<krog::HeckleObservation<OBSN>>> & obsmap)
... then it becomes easy to miss that the first 'obsmap' is a const reference and the second is not.
This will make a difference when you have more then one const/volatile modifiers. Then putting it to the left of the type is still valid but will break the consistency of the whole declaratiion. For example:
T const * const *p;
means that p is a pointer to const pointer to const T and you consistenly read from right to left.
const T * const *p;
means the same but the consistency is lost and you have to remember that leftmost const/volatile is bound to T alone and not T *.
I think is personal preference. There is no difference between the two variants.
My reasoning is as follows:
It does seem to roll off the tongue better if you write "const T&" but when you do that you end up with the ambiguous, "constant T reference." I've seen this cause problems more than once in the understandability of code that allowed someone, even semi-experienced, to misinterpret what something meant or how to declare a more complex type.
I can't think of any example right now but more than once I've answered questions about type declarations and constness where the problem was caused by the habit of using "const T &" instead of "T const &". I used to write it that way as well and when I became a Sr. Developer, someone in charge of mentoring and creating code standards in projects, I found it much easier for entry level developers when I force everyone to use "T const&". I suppose one rather trivial, rookie mistake would be why does this code compile?
const T* t = f();
t = 0; // assignment to const?? - no, it is not the T* that is const, just the T.
When you learn to read it the way that the compiler does it becomes much easier to understand what any given complex type is as well as allowing you to more readily declare complex types when you need to. By complex types I'm talking about things such as:
T const * const &
When you know that the compiler reads right to left, inside to out, what that means becomes quite apparent and when it is necessary to write one you can do so easily: reference to constant pointer to a constant T. Now write the declaration of a "reference to a pointer to a constant pointer to a T". If you simply use left to right notation I think you'll find this quite easy.
In short, though it initially seems unnatural teaching oneself to use right->left grammar ALL the time, instead of only when it is required (because it often is), you'll find it much easier to remember what a line of code means and how to write what you mean. It's sort of along the same lines of why I disallow "," in declarations:
T* ptr1 = 0, ptr2 = 0; // oops!!!
// do it this way please!
T* ptr1 = 0;
T* ptr2 = 0;
Technically it's all the same but when you try to get a bunch of people of varying capacities working on the same thing you'll tend to make sure everyone uses whatever method is the easiest to understand and use. My experience has taught me that "T const&" is that method.
I think some people simply prefer to read the declarations from right to left. const
applies to the left-hand token, except when there is nothing there and it applies on the right-hand token. Hence const T&
involves the "except"-clause and can perhaps be thought more complicated (in reality both should be as easy to understand).
Compare:
const T* p; (pointer to T that is const)
T const* p; (pointer to const T) //<- arguable more natural to read
T* const p; (const pointer to T)
Being as code is predominantly English-based, programmers tend to read left to right, so const T&
reads naturally to us where the compiler reads it inside out right to left so T const&
reads naturally(reference to a const T)