Why is `const T&` not sure to be const?

C++TemplatesConstantsFunction TemplatesConst Reference

C++ Problem Overview


template<typename T>
void f(T a, const T& b)
{
    ++a; // ok
    ++b; // also ok!
}

template<typename T>
void g(T n)
{
    f<T>(n, n);
}

int main()
{
    int n{};
    g<int&>(n);
}

Please note: b is of const T& and ++b is ok!

Why is const T& not sure to be const?

C++ Solutions


Solution 1 - C++

Welcome to const and reference collapsing. When you have const T&, the reference gets applied to T, and so does the const. You call g like

g<int&>(n);

so you have specified that T is a int&. When we apply a reference to an lvalue reference, the two references collapse to a single one, so int& & becomes just int&. Then we get to the rule from [dcl.ref]/1, which states that if you apply const to a reference it is discarded, so int& const just becomes int& (note that you can't actually declare int& const, it has to come from a typedef or template). That means for

g<int&>(n);

you are actually calling

void f(int& a, int& b)

and you are not actually modifying a constant.


Had you called g as

g<int>(n);
// or just
g(n);

then T would be int, and f would have been stamped out as

void f(int a, const int& b)

Since T isn't a reference anymore, the const and the & get applied to it, and you would have received a compiler error for trying to modify a constant variable.

Solution 2 - C++

I know that there is already an accepted answer which is correct but just to add to it a little bit, even outside the realm of templates and just in function declarations in general...

( const T& ) 

is not the same as

( const T )

In your example which matches the first, you have a const reference. If you truly want a const value that is not modifiable remove the reference as in the second example.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionxmllmxView Question on Stackoverflow
Solution 1 - C++NathanOliverView Answer on Stackoverflow
Solution 2 - C++Francis CuglerView Answer on Stackoverflow