c++referencec++20

How to understand "constness is shallow" with regard to references (as stated in cppreference.com)?


While studying the cppreference spec of std::atomic_ref, I found myself brooding over the following sentence:

Like references in the core language, constness is shallow for std::atomic_ref - it is possible to modify the referenced value through a const std::atomic_ref object.

I see that e.g. in const std::atomic_ref<int> aref, const makes aref constant and not the object aref is referencing to.

What confuses me is the first part of the sentence: "Like references in the core language, constness is shallow...". References in the core language like const int& ref are not shallow, are they?


Solution

  • The short answer is that the sentence is not refering to references in the narrow sense.

    I see that e.g. in const std::atomic_ref<int> aref, const makes aref constant and not the object aref is referencing to.

    Yes, exactly.

    What confuses me is the first part of the sentence: "Like references in the core language, constness is shallow...". References in the core language like const int& ref are not shallow, are they?

    The sentence does not refer to references like int& or const int& but to references in the broader sense like int * vs const int*. That the sentence contains a link to the article about references appears to be an editing mistake.


    cppreference is not "the specs". It tries to be close to the wording in the standard while being human readable. Not always this goes without friction.

    I did not actually find anything in N4928 that looks like it was the actual source for the sentence you quote.

    I agree that the sentence is somewhat confusing. I suppose it tries to say that a const std::atomic_ref<int> references an int not a const int. This is the same with plain pointers.

    References are special because there is no top const for references. References can be thought of to be always constant. You cannot rebind a reference. const int& is a reference to const int and int& is a reference to int. If you follow the link in your quote, you can read about references:

    Reference types cannot be cv-qualified at the top level; there is no syntax for that in declaration, and if a qualification is added to a typedef-name or decltype specifier,(since C++11) or type template parameter, it is ignored.

    I suppose this is what your quote refers to, but it's somewhat confusing to draw that parallel, because you can have a const qualified std::atomic_ref while you simply cannot add a top level const to a reference type. As stated in a comment, add_const_t<T&> is still T&.


    PS: As stated in comments, the sentence is less confusing if you read it as referring to "references" in the general sense. std::atomic_ref has shallow const just like pointers. For me, the confusion starts when they link to the article about references, implying the sentence does refer to references (not in the broader sense). However, browsing the history of the article, I found that the link was added only later. Perhaps it would be better to remove it again.

    PPS: std::reference_wrapper is another "reference-like" type and it has shallow const too. const reference_wrapper<T> has a get method that returns T&. You have to use std::reference_wrapper<const T> to model a const T&.